EF Fluent API:为派生自基本摘要 class 的每个实体设置 属性
EF Fluent API: Set property for each entity derived from a base abstract class
我有一个 BaseClass,它是抽象的,有很多抽象属性。
我有十几个(它可能会增长)实体,它们是 Entity Framework 的一部分,每个实体都派生自 BaseClass。
我正在努力避免必须这样做:
modelBuilder.Entity<Entity1>().HasKey(t => t.Id);
modelBuilder.Entity<Entity2>().HasKey(t => t.Id);
modelBuilder.Entity<Entity3>().HasKey(t => t.Id);
...
对于每个 属性 和每个实体,因为这看起来非常浪费并且会产生大量代码重复。我尝试通过以下方式获取从 BaseClass 派生的命名空间中的所有实体:
var derivedEntities = Assembly.GetExecutingAssembly().GetTypes().
Where(t => t.Namespace == "My.Entities" && t.IsAssignableFrom(typeof(BaseClass)));
但是,接下来的合乎逻辑的步骤似乎是:
foreach (var entity in derivedEntities)
{
modelBuilder.Entity<entity>().HasKey(t => t.Id);
}
但不会编译,因为
"entity is a variable, but is used like a type".
我想通了:
public class BaseObjectConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
where TEntity : BaseObject
{
public BaseObjectConfiguration()
{
// Mapped
HasKey(t => t.Id);
Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(t => t.Name).IsRequired().HasMaxLength(100);
Property(t => t.DisplayName).IsOptional().HasMaxLength(100);
Property(t => t.Alias).IsOptional().HasMaxLength(100);
Property(t => t.SourceId).IsRequired();
Property(t => t.AccessLevel).IsRequired();
Property(t => t.CreatedOn).IsOptional();
Property(t => t.CreatedBy).IsOptional().HasMaxLength(50);
Property(t => t.ModifiedOn).IsOptional();
Property(t => t.ModifiedBy).IsOptional().HasMaxLength(50);
//// Base Entity Ignores (Not Mapped)
Ignore(t => t.SomeIgnoredProperty);
Ignore(t => t.SomeIgnoredProperty2);
Ignore(t => t.SomeIgnoredProperty3);
}
}
然后,在OnModelCreating里面的DbContext:
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity1>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity2>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity3>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity4>());
...
// Specific mappings options for each entity:
modelBuilder.Entity<Entity1>().HasRequired(t => t.NodeTypeEntity).
WithMany(t => t.Nodes).HasForeignKey(t => t.NodeTypeId);
modelBuilder.Entity<NWatchNode>().HasOptional(t => t.Parent).
WithMany(t => t.Children).HasForeignKey(t => t.ParentId);
...
我有一个 BaseClass,它是抽象的,有很多抽象属性。
我有十几个(它可能会增长)实体,它们是 Entity Framework 的一部分,每个实体都派生自 BaseClass。
我正在努力避免必须这样做:
modelBuilder.Entity<Entity1>().HasKey(t => t.Id);
modelBuilder.Entity<Entity2>().HasKey(t => t.Id);
modelBuilder.Entity<Entity3>().HasKey(t => t.Id);
...
对于每个 属性 和每个实体,因为这看起来非常浪费并且会产生大量代码重复。我尝试通过以下方式获取从 BaseClass 派生的命名空间中的所有实体:
var derivedEntities = Assembly.GetExecutingAssembly().GetTypes().
Where(t => t.Namespace == "My.Entities" && t.IsAssignableFrom(typeof(BaseClass)));
但是,接下来的合乎逻辑的步骤似乎是:
foreach (var entity in derivedEntities)
{
modelBuilder.Entity<entity>().HasKey(t => t.Id);
}
但不会编译,因为
"entity is a variable, but is used like a type".
我想通了:
public class BaseObjectConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
where TEntity : BaseObject
{
public BaseObjectConfiguration()
{
// Mapped
HasKey(t => t.Id);
Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(t => t.Name).IsRequired().HasMaxLength(100);
Property(t => t.DisplayName).IsOptional().HasMaxLength(100);
Property(t => t.Alias).IsOptional().HasMaxLength(100);
Property(t => t.SourceId).IsRequired();
Property(t => t.AccessLevel).IsRequired();
Property(t => t.CreatedOn).IsOptional();
Property(t => t.CreatedBy).IsOptional().HasMaxLength(50);
Property(t => t.ModifiedOn).IsOptional();
Property(t => t.ModifiedBy).IsOptional().HasMaxLength(50);
//// Base Entity Ignores (Not Mapped)
Ignore(t => t.SomeIgnoredProperty);
Ignore(t => t.SomeIgnoredProperty2);
Ignore(t => t.SomeIgnoredProperty3);
}
}
然后,在OnModelCreating里面的DbContext:
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity1>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity2>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity3>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity4>());
...
// Specific mappings options for each entity:
modelBuilder.Entity<Entity1>().HasRequired(t => t.NodeTypeEntity).
WithMany(t => t.Nodes).HasForeignKey(t => t.NodeTypeId);
modelBuilder.Entity<NWatchNode>().HasOptional(t => t.Parent).
WithMany(t => t.Children).HasForeignKey(t => t.ParentId);
...