gpt4 book ai didi

c# - 如何将通用配置应用于 ef core 中的所有实体

转载 作者:太空狗 更新时间:2023-10-30 00:47:52 25 4
gpt4 key购买 nike

我的应用程序中有从基本实体派生的实体,该应用程序使用 ef 核心代码优先方法。

基类

public abstract class BaseEntity<T> : IEntity<T>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public T Id { get; set; }

object IEntity.Id { get { return Id; } set { } }

private DateTime? createdOn;
[DataType(DataType.DateTime)]
public DateTime CreatedOn { get => createdOn ?? DateTime.Now; set => createdOn = value; }

[DataType(DataType.DateTime)]
public DateTime? ModifiedOn { get; set; }

public bool IsDeleted { get; set; }
// Auto increment for all entities.
public int OrderId { get; set; }
}

和一个实体

public class UserEntity : BaseEntity<int>
{
public string EmployeeId { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
}

我可以在 OnModelCreating 每个实体 中对属性 OrderId 应用 .ValueGeneratedOnAdd() 方法,但是,有没有一种方法可以在不重复自己的情况下对所有实体应用通用规则?

最佳答案

由于缺少自定义约定,您可以使用典型的 modelBuilder.Model.GetEntityTypes()循环,识别目标实体类型并调用公共(public)配置。

你的情况下的识别有点复杂,因为基 generic 类,但可以通过向下迭代 Type.BaseType 来实现并检查 BaseEntity<> .找到它后,您可以检索通用参数 T稍后您将需要它。

如果您不想使用通用类实现IEnityTypeConfiguration<TEntity> , 然后想法是将实现放在 generic constrained 方法中,像这样

static void Configure<TEntity, T>(ModelBuilder modelBuilder)
where TEntity : BaseEntity<T>
{
modelBuilder.Entity<TEntity>(builder =>
{
builder.Property(e => e.OrderId).ValueGeneratedOnAdd();
});
}

传递实际实体类型 TEntitymodelBuilder.Enity方法至关重要,否则 EF Core 会将您传递的任何内容视为实体类型并配置 TPH 继承。

调用方法需要反射——找到泛型方法定义,使用MakeGenericMethod然后 Invoke .

下面是封装在静态类中的所有内容:

public static class BaseEntityConfiguration
{
static void Configure<TEntity, T>(ModelBuilder modelBuilder)
where TEntity : BaseEntity<T>
{
modelBuilder.Entity<TEntity>(builder =>
{
builder.Property(e => e.OrderId).ValueGeneratedOnAdd();
});
}

public static ModelBuilder ApplyBaseEntityConfiguration(this ModelBuilder modelBuilder)
{
var method = typeof(BaseEntityConfiguration).GetTypeInfo().DeclaredMethods
.Single(m => m.Name == nameof(Configure));
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
if (entityType.ClrType.IsBaseEntity(out var T))
method.MakeGenericMethod(entityType.ClrType, T).Invoke(null, new[] { modelBuilder });
}
return modelBuilder;
}

static bool IsBaseEntity(this Type type, out Type T)
{
for (var baseType = type.BaseType; baseType != null; baseType = baseType.BaseType)
{
if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(BaseEntity<>))
{
T = baseType.GetGenericArguments()[0];
return true;
}
}
T = null;
return false;
}
}

现在您需要做的就是从您的 OnModelCreating 中调用它覆盖:

modelBuilder.ApplyBaseEntityConfiguration();

关于c# - 如何将通用配置应用于 ef core 中的所有实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53275567/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com