ibu*_*ubi 4 c# entity-framework-core
我的应用程序中具有从基本实体派生的实体,该基本实体使用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; }
}
Run Code Online (Sandbox Code Playgroud)
和一个实体
public class UserEntity : BaseEntity<int>
{
public string EmployeeId { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我可以将.ValueGeneratedOnAdd()方法应用于每个实体的属性OrderId,但是,有没有一种方法可以对所有实体应用通用规则而无需自己重复?OnModelCreating
由于缺少自定义约定,您可以使用典型的modelBuilder.Model.GetEntityTypes()循环,识别目标实体类型并调用通用配置。
由于基本的泛型类,因此您的情况下的识别有点复杂,但是可以通过向下迭代Type.BaseType并检查来实现BaseEntity<>。找到它之后,您可以检索T以后需要的通用参数。
如果您不想使用泛型类实现IEnityTypeConfiguration<TEntity>,那么您的想法是将实现放在这样的泛型约束方法中
static void Configure<TEntity, T>(ModelBuilder modelBuilder)
where TEntity : BaseEntity<T>
{
modelBuilder.Entity<TEntity>(builder =>
{
builder.Property(e => e.OrderId).ValueGeneratedOnAdd();
});
}
Run Code Online (Sandbox Code Playgroud)
将实际的实体类型传递TEntity给modelBuilder.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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您需要的是从OnModelCreating覆盖中调用它:
modelBuilder.ApplyBaseEntityConfiguration();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1110 次 |
| 最近记录: |