// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
///
/// 表种子数据代码生成策略类
///
[CodeGenStrategy(CodeGenSceneEnum.TableSeedData)]
public class TableSeedDataCodeGenStrategy : CodeGenEntityStrategyBase, ISingleton
{
private readonly TemplateContextOutput _template = new() { Name = "SeedData.cs.vm", OutPath = "SeedData/{ModuleName}SeedData.cs" };
public override async Task> GenerateCode(CreateSeedDataInput input)
{
var config = _dbConnectionOption.ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == input.ConfigId) ?? throw Oops.Oh(ErrorCodeEnum.db1004);
input.Position = string.IsNullOrWhiteSpace(input.Position) ? "X.Core" : input.Position;
var db = _db.AsTenant().GetConnectionScope(input.ConfigId);
var tableInfo = db.DbMaintenance.GetTableInfoList(false).First(u => u.Name == input.TableName); // 表名
List dbColumnInfos = db.DbMaintenance.GetColumnInfosByTableName(input.TableName, false); // 所有字段
IEnumerable entityInfos = await GetEntityInfos();
Type entityType = null;
foreach (var item in entityInfos)
{
if (tableInfo.Name.ToLower() != (config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(item.DbTableName) : item.DbTableName).ToLower()) continue;
entityType = item.Type;
break;
}
if (entityType == null) throw Oops.Oh(ErrorCodeEnum.db1003);
input.EntityName = entityType.Name;
input.SeedDataName = entityType.Name + "SeedData";
if (!string.IsNullOrWhiteSpace(input.Suffix)) input.SeedDataName += input.Suffix;
// 查询所有数据
var query = db.QueryableByObject(entityType);
// 优先用创建时间排序
DbColumnInfo orderField = dbColumnInfos.FirstOrDefault(u => u.DbColumnName.ToLower() is "create_time" or "createtime");
if (orderField != null) query = query.OrderBy(orderField.DbColumnName);
// 优先用创建时间排序,再使用第一个主键排序
if (dbColumnInfos.Any(u => u.IsPrimarykey))
query = query.OrderBy(dbColumnInfos.First(u => u.IsPrimarykey).DbColumnName);
var records = ((IEnumerable)await query.ToListAsync()).ToDynamicList();
// 过滤已存在的数据
if (input.FilterExistingData && records.Any())
{
// 获取实体类型-所有种数据数据类型
var entityTypes = App.EffectiveTypes.Where(u => u.FullName != null && !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false) && u.FullName.EndsWith("." + input.EntityName))
.Where(u => !u.GetCustomAttributes().Any())
.ToList();
if (entityTypes.Count == 1) // 只有一个实体匹配才能过滤
{
// 获取实体的主键对应的属性名称
var pkInfo = entityTypes[0].GetProperties().FirstOrDefault(u => u.GetCustomAttribute()?.IsPrimaryKey == true);
if (pkInfo != null)
{
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces()
.Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>)) && i.GenericTypeArguments[0] == entityTypes[0])).ToList();
// 可能会重名的种子数据不作为过滤项
string doNotFilterFullName1 = $"{input.Position}.SeedData.{input.SeedDataName}";
string doNotFilterFullName2 = $"{input.Position}.{input.SeedDataName}"; // Core中的命名空间没有SeedData
PropertyInfo idPropertySeedData = records[0].GetType().GetProperty("Id");
for (int i = seedDataTypes.Count - 1; i >= 0; i--)
{
string fullName = seedDataTypes[i].FullName;
if ((fullName == doNotFilterFullName1) || (fullName == doNotFilterFullName2)) continue;
// 删除重复数据
var instance = Activator.CreateInstance(seedDataTypes[i]);
var hasDataMethod = seedDataTypes[i].GetMethod("HasData");
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast