如何在Entity Framework Core中创建组合键,该组合键是基类和派生类的组合

时间:2019-01-06 04:51:29

标签: c# entity-framework asp.net-core migration

我需要在Entity Framework中创建复合键。

我的基类键是“ Guid”,我希望学生班级中有一些独特的东西,例如“ ID”,它可以被读取。例如“ STUD01”,它确实需要可读的唯一数据。

[NotMapped]
public class BaseEntity
{
     public Guid Key { get; set; }
     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 string 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)
 {
     modelBuilder.Entity<BaseEntity>().Property(x => x.DateCreated).HasDefaultValueSql("GETDATE()");
     modelBuilder.Entity<BaseEntity>().Property(x => x.DateModified).HasDefaultValueSql("GETDATE()");

     //here is my composite key
     modelBuilder.Entity<Student>().HasKey(c => new { c.Key, c.Id });
 }

我已经运行以下迁移命令来创建脚本和更新数据库

Add-Migration -Name "InitialMigration" -Context "SchoolContext"

我得到这个错误:

  

不能在“学生”上配置键,因为它是派生类型。必须在根类型“ BaseClass”上配置密钥。如果您不打算将'BaseClass'包含在模型中,请确保它不包含在上下文的DbSet属性中,在对ModelBuilder的配置调用中引用,或从包含的类型的导航属性中引用在模型中。

如何实现?

我正在使用ASP.NET Core 2.1

1 个答案:

答案 0 :(得分:1)

问题在于Row( children: <Widget>[ Expanded( child: Divider() ), Text("OR"), Expanded( child: Divider() ), ] ) 的数据注释不会忽略表的创建,因为[Not Mapped]始终具有比数据注释(属性)更高的优先级。因此,您可以在Fluent API的{​​{1}}配置之后调用modelBuilder.Ignore<BaseEntity>();,但是调用BaseEntity会丢失OnModelCreating配置。

所以最好的解决方案是:

编写modelBuilder.Ignore<BaseEntity>();的配置,如下所示:

BaseEntity

然后按如下所示编写BaseEntity的配置:

public class BaseEntityConfigurations<TEntity> : IEntityTypeConfiguration<TEntity> where TEntity : BaseEntity
{
    public virtual void Configure(EntityTypeBuilder<TEntity> builder)
    {
        builder.Property(x => x.Key).HasDefaultValueSql("NEWID()");
        //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

       // composite key
        builder.HasKey(c => new { c.Key, c.Id });
    }
}

现在一切正常!

注意:如果您已经有一个数据库,则该数据库在迁移时将不起作用。您必须在初始迁移时生成全新的表,因为Entity Framework核心无法在迁移时更改主键。