实体框架核心2.0:如何配置抽象基类

时间:2018-04-23 21:38:32

标签: sql-server ef-code-first entity-framework-core asp.net-core-2.0 ef-fluent-api

我有一个基本模型:

public abstract class Status
{
     public string updateUserName { get; set; }
}

然后是扩展上面定义的基本模型的模型:

public class Item : Status
{
     public int Id { get; set; }
     public string Description { get; set; }
}

然后我为每个定义了配置类:

public class ItemConfiguration : IEntityTypeConfiguration<Item>
{
    public void Configure(EntityTypeBuilder<Item> builder)
    {
        builder.ToTable("Item", "dbo").HasKey(c => c.Id);
        builder.Property(c => c.Description).IsRequired().HasMaxLength(100);
    }
}

public class StatusConfiguration : IEntityTypeConfiguration<Status>
{
    public void Configure(EntityTypeBuilder<Status> builder)
    {
        builder.Property(c => c.updateUserName).IsRequired().HasMaxLength(50);
    }

现在,我有以下Context类:

public class TestDbContext : DbContext
{
    public TestDbContext(DbContextOptions<TestDbContext> options) : base(options)
    {
    }

    public DbSet<Item> Item { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new ItemConfiguration());
    }
}

我试图弄清楚如何将StatusConfiguration类中定义的Status模型配置应用于扩展到它的所有模型(在此示例中只有一个:Item)。我想避免每次使用时定义相同的Status模型配置。 Status模型基本上是与每个Item记录关联的元数据(即数据库中的一个Item表,包含在两个模型中定义的所有属性;仅此而已,并且没有更少)。

例如,我当前的实现是不使用StatusConfiguration类的以下ItemConfiguration类:

public class ItemConfiguration : IEntityTypeConfiguration<Item>
{
    public void Configure(EntityTypeBuilder<Item> builder)
    {
        builder.ToTable("Item", "dbo").HasKey(c => c.Id);
        builder.Property(c => c.Description).IsRequired().HasMaxLength(100);
        builder.Property(c => c.updateUserName).IsRequired().HasMaxLength(50);
    }
}

当前实现正常工作并按预期迁移到数据库。我只是在寻找一种更易于管理的方式。

我的假设是我可以扩展ItemConfiguration类以包含StatusConfiguration类,但无法在线查找该方法的示例。我希望有更多经验的人能够指出我正确的方向吗?

如果有其他信息有用,请告诉我。

1 个答案:

答案 0 :(得分:21)

如果我理解正确,Status只是一个基类,而不是参与Database Inheritance的基本实体

在这种情况下,永远不要直接在实体模型和配置中引用Status类,即没有DbSet<Status>,没有类型Status或{{ICollection<Status>的导航属性,这一点非常重要。 1}},没有modelBuilder.Entity<Status>()来电,没有IEntityTypeConfiguration<Status>

相反,您总是需要引用从Status继承的具体类型。为了重用配置代码,您应该使用约束泛型方法或类并传递具体的实体类型。

由于您使用的是IEntityTypeConfiguration类,因此最自然的做法是使您的StatusConfiguration类具有通用性:

public class StatusConfiguration<TEntity> : IEntityTypeConfiguration<TEntity>
    where TEntity : Status
{
    public virtual void Configure(EntityTypeBuilder<TEntity> builder)
    {
        builder.Property(c => c.updateUserName).IsRequired().HasMaxLength(50);
    }
}

让衍生的实体配置类派生自它:

public class ItemConfiguration : StatusConfiguration<Item>
{
    public override void Configure(EntityTypeBuilder<Item> builder)
    {
        base.Configure(builder); // <--
        builder.ToTable("Item", "dbo").HasKey(c => c.Id);
        builder.Property(c => c.Description).IsRequired().HasMaxLength(100);
    }
}