配置抽象基类而不在 EF Core 中创建表 [重复]
Posted
技术标签:
【中文标题】配置抽象基类而不在 EF Core 中创建表 [重复]【英文标题】:Configuring abstract base class without creating table in EF Core [duplicate] 【发布时间】:2019-01-05 06:11:18 【问题描述】:我通过创建BaseEntity.cs
类为每个实体添加了DateCreated
、UserCreated
、DateModified
和UserModified
字段。我的要求是生成单个表,其中包含base
类的所有字段作为列。
public class BaseEntity
public DateTime? DateCreated get; set;
public string UserCreated get; set;
public DateTime? DateModified get; set;
public string UserModified get; set;
这是我的Student
课程
public class Student : BaseEntity
public int Id get; set;
public string Name get; set;
这是我的上下文类
public class SchoolContext: DbContext
public LibraContext(DbContextOptions<SchoolContext> options)
: base(options)
public DbSet<Student> Students get; set;
protected override void OnModelCreating(ModelBuilder modelBuilder)
//CreatedDate
modelBuilder.Entity<BaseEntity>().Property(x => x.DateCreated).HasDefaultValueSql("GETDATE()");
//Updated Date
modelBuilder.Entity<BaseEntity>().Property(x => x.DateModified).HasDefaultValueSql("GETDATE()");
我已运行以下迁移命令来创建脚本和更新数据库
Add-Migration -Name "InitialMigration" -Context "SchoolContext"
update-database
它在 SQL Server 数据库中创建了单独的表 BaseEntity
和 Student
。我的期望是创建一个 Student
表,其中所有 BaseEntity
字段作为列。
如何实现?
我正在使用 ASP.NET CORE2.1
【问题讨论】:
您想要一个将基类的所有字段作为列的单个表。然而我的期望是创建一个Student 表,其中所有BaseEntity 字段作为列。对我来说这是矛盾的。至于后者,你可能喜欢this的做法。 看link 查看标记为重复的问题的答案。罪魁祸首是您不应该在模型导航属性或流式 API 中直接引用BaseEntity
。帖子中具体代码的问题是modelBuilder.Entity<BaseEntity>()
,它将BaseEntity
标记为TPH基础实体。
【参考方案1】:
根据Microsoft Documentation,您可以使用[NotMapped]
数据注释或modelBuilder.Ignore<TEntity>();
忽略BaseEntity
的表创建,如下所示:
但在您的情况下,[NotMapped]
对您没有帮助,因为Fluent API
始终具有比数据注释(属性)更高的优先级。所以你可以在OnModelCreating
中的BaseEntity
配置之后调用modelBuilder.Ignore<BaseEntity>();
,但调用modelBuilder.Ignore<BaseEntity>();
将丢失BaseEntity
配置。
所以就我而言,最好的解决方案如下:
为BaseEntity
编写配置如下:
public class BaseEntityConfigurations<TEntity> : IEntityTypeConfiguration<TEntity> where TEntity : BaseEntity
public virtual void Configure(EntityTypeBuilder<TEntity> builder)
//CreatedDate
builder.Property(x => x.DateCreated).HasDefaultValueSql("GETDATE()");
//Updated Date
builder.Property(x => x.DateModified).HasDefaultValueSql("GETDATE()");
然后为Student
编写配置如下:
public class StudentConfigurations : BaseEntityConfigurations<Student>
public override void Configure(EntityTypeBuilder<Student> builder)
base.Configure(builder); // Must call this
// other configurations here
然后在OnModelCreating
中如下:
protected override void OnModelCreating(ModelBuilder modelBuilder)
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new StudentConfigurations());
迁移将生成唯一的Student
表,BaseEntity
配置如下:
migrationBuilder.CreateTable(
name: "Students",
columns: table => new
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
DateCreated = table.Column<DateTime>(nullable: true, defaultValueSql: "GETDATE()"),
UserCreated = table.Column<string>(nullable: true),
DateModified = table.Column<DateTime>(nullable: true, defaultValueSql: "GETDATE()"),
UserModified = table.Column<string>(nullable: true),
Name = table.Column<string>(nullable: true)
,
constraints: table =>
table.PrimaryKey("PK_Students", x => x.Id);
);
【讨论】:
听起来不错,同时我也找到了不同的方法来解决它。请查看我的答案并进行审核。 Fluent API(在这种情况下为modelBuilder.Entity<BaseEntity>()
)比数据注释(属性)具有更高的优先级。这绝对是不是解决方案,因为该属性与流畅的配置冲突。
@IvanStoev 不明白!进一步解释我。您是否希望致电modelBuilder.Ignore<BaseEntity>();
?
这消除了错误,但现在属性设置(DefaultValueSql
等)丢失(不包含在生成的迁移代码中)。所以不幸的是,黑客不起作用。处理这种情况的正确方法显示在重复链接和其他一些类似的帖子中,它迭代 modelBuilder.Model.GetEntityTypes()
并为所有派生实体类型调用一些通用配置代码。这种情况下的基类永远不应该被指定为实体,也不能为所有派生实体配置一次其属性。
我喜欢你的创造力和热情,真的:)【参考方案2】:
TPC 模式目前在 backlog 上,这意味着它正在考虑作为一项功能包含在内,但尚未确定日期。
read more.
【讨论】:
【参考方案3】:我已经通过简单的更改解决了这个问题!我们必须在modelbuilder
中使用Student
实体。我被误用了BaseEntity
protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<Student>().Property(x => x.Created).HasDefaultValueSql("GETDATE()");
modelBuilder.Entity<Student>().Property(x => x.Updated).HasDefaultValueSql("GETDATE()");
未解决问题:order number
无法控制生成表列的顺序。 .net core 目前不支持此功能。
【讨论】:
这不是最好的解决方案。如果您有另一个名为Teacher
的模型类继承自BaseEntity
,那么它将无法工作。您必须再次为Teacher
模型类编写配置。现在想想如果你有 100 个实体怎么办?你必须写100次。所以请按照我的解决方案。
没错,我同意你的看法。让我试试你的解决方案并及时通知你
好的!检查并确认!
我有小问题。我有复合键要求,它是基类和派生类的键的组合。 modelBuilder.Entity以上是关于配置抽象基类而不在 EF Core 中创建表 [重复]的主要内容,如果未能解决你的问题,请参考以下文章