Entity Framework Core 2.0:如何配置一次抽象基类

我有一个基本模型:

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

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

Then a model which extends the base model defined above:

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

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

Then I have defined configuration classes for each:

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 类:

Now, I have the following Context class:

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 表,包含两个模型中定义的所有属性;仅此而已).

I'm trying to figure out how to apply the Status model configurations defined in the StatusConfiguration class to all the models that extend to it (only one in this example: Item). I would like to avoid defining the same Status model configuration every time it gets used. The Status model will essentially be meta data associated with each Item record (i.e. one Item table in database containing all properties defined in both models; nothing more, and nothing less).

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

For example, my current implementation is the following ItemConfiguration class without using the StatusConfiguration class:

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);
    }
}

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

That current implementation works correctly and migrates to the database as intended. I'm simply looking for a more manageable way going forward.

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

My assumption is that I could extend the ItemConfiguration class to include the StatusConfiguration class but cannot find an example of that method online. I'm hoping someone with a little more experience could kindly point me in the right direction?

让我知道其他信息是否有帮助.

Let me know if additional information would be helpful.

推荐答案

如果我理解正确,Status 只是一个基类,而不是一个参与的基实体数据库继承.

If I understand correctly, the Status is just a base class and not a base entity participating in Database Inheritance.

在这种情况下,永远不要在实体模型和配置中直接引用 Status 类,即没有 DbSet,没有 类型的导航属性,这一点很重要状态ICollection,没有modelBuilder.Entity()调用,也没有IEntityTypeConfiguration.

In such case it's important to never refer to Status class directly inside entity model and configuration, i.e. no DbSet<Status>, no navigation properties of type Status or ICollection<Status>, no modelBuilder.Entity<Status>() calls and no IEntityTypeConfiguration<Status>.

相反,您始终必须引用从 Status 继承的具体类型.为了重用配置代码,您应该使用约束泛型方法或类并传递具体的实体类型.

Instead, you always have to refer to the concrete types inheriting from the Status. In order to reuse configuration code, you should use constrained generic methods or classes and pass the concrete entity types.

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

Since you are using IEntityTypeConfiguration classes, probably the most natural is to make your StatusConfiguration class generic:

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

并让派生实体配置类从它派生:

and let derived entity configuration classes derive from it:

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);
    }
}

相关文章