繁体   English   中英

如何在 Entity Framework Core 中创建由基类和派生类组合而成的复合键

[英]How do I create composite key which is combination of base class and derived class in Entity Framework Core

我需要在实体框架中创建复合键。

我的基类键是“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"

我收到这个错误:

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

如何实现?

我正在使用 ASP.NET Core 2.1

问题是[Not Mapped]数据注释不会忽略表创建,因为Fluent API始终比数据注释(属性)具有更高的优先级。 所以你可以调用modelBuilder.Ignore<BaseEntity>(); OnModelCreatingBaseEntity配置之后调用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 });
    }
}

然后在OnModelCreating如下:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.ApplyConfiguration(new StudentConfigurations());
}

现在一切正常!

注意:如果您已经有一个数据库,那么它将无法用于迁移。 您必须在初始迁移时生成全新的表,因为实体框架核心无法通过迁移更改主键。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM