C# 如何在EF Core中自动映射TPH派生类?

C# 如何在EF Core中自动映射TPH派生类?,c#,entity-framework,.net-core,entity-framework-core,discriminator,C#,Entity Framework,.net Core,Entity Framework Core,Discriminator,默认情况下,EF6将映射每个层次表(TPH)的基本抽象类及其派生类 EF核心不再遵循此逻辑,并要求选择派生类。文件规定: 按照惯例,在数据库上的DbSet属性中公开的类型 上下文作为实体包含在模型中。实体类型是 还包括OnModelCreating方法中指定的,以及任何 通过递归浏览导航找到的类型 发现的其他实体类型的属性 如果您有一些子类型,那么使用这种方法并不难,因为您可以将它们添加为dbset,或者为每个子类型添加一个HasDiscriminator().HasValue(),映射如下:

默认情况下,EF6将映射每个层次表(TPH)的基本抽象类及其派生类

EF核心不再遵循此逻辑,并要求选择派生类。文件规定:

按照惯例,在数据库上的DbSet属性中公开的类型 上下文作为实体包含在模型中。实体类型是 还包括OnModelCreating方法中指定的,以及任何 通过递归浏览导航找到的类型 发现的其他实体类型的属性

如果您有一些子类型,那么使用这种方法并不难,因为您可以将它们添加为dbset,或者为每个子类型添加一个HasDiscriminator().HasValue(),映射如下:

builder.HasDiscriminator()
    .HasValue<CommaSymbolRule>("CommaSymbolRule")
    .HasValue<DashSymbolRule>("DashSymbolRule")
    .HasValue<IsNumericSymbolRule>("IsNumericSymbolRule")
    .HasValue<IsPunctuationSymbolRule>("IsPunctuationSymbolRule")
    .HasValue<PeriodSymbolRule>("PeriodSymbolRule")
builder.HasDiscriminator()
.HasValue(“CommaSymbolRule”)
.HasValue(“DashSymbolRule”)
.HasValue(“IsNumericSymbolRule”)
.HasValue(“ispuncationsymbolRule”)
.HasValue(“周期符号规则”)
在某些情况下,这是次优的,因为您可能有许多派生类。在我的例子中,我有一个规则引擎,不想单独映射每个规则


是否有一种方法可以在每个层次结构场景中自动映射EF核心表中基类的子类型,而不必手动添加它们?

我认为在EF核心中可能有一种方法可以做到这一点,但发现没有

我与EF团队讨论了为什么自动选择加入不再是默认设置,他们对可能非常有效的“组装扫描解决方案”的稳定性表示担忧。目前,他们似乎对在这些方面添加新功能不太感兴趣

这是我的想法。它将程序集扫描放在映射代码中,但似乎有效

首先,我创建了一个扩展方法来获取派生类(可以选择按名称忽略特定类型):

然后对EF核心映射中的基类使用类似于此的代码,切换出您的类型(即:此代码中的“SymbolRule”):

public void配置(EntityTypeBuilder)
{
builder.ToTable(“SymbolRule”);//我的示例表
HasKey(t=>t.SymbolRuleId);//我的示例键
foreach(typeof(SymbolRule).GetDerivedClasses()中的变量类型)
{
builder.HasDiscriminator()
.HasValue(类型、类型、名称);
}
}
foreach从基类中获取派生类并循环它们,并为每个派生类添加一个鉴别器类型

public static Type[] GetDerivedClasses(this Type type, string[] ignoreTypeNames = null) 
{
    ignoreTypeNames = ignoreTypeNames ?? new string[0];

    return Assembly.GetAssembly(type)
                    .GetTypes()
                    .Where
                    (
                        t => t.IsSubclassOf(type) &&
                        (!ignoreTypeNames?.Any(t.Name.Contains) ?? false)
                    )
                    .OrderBy(o => o.Name)
                    .ToArray();
}
public void Configure(EntityTypeBuilder<SymbolRule> builder)
{
    builder.ToTable("SymbolRule");       // my example table
    builder.HasKey(t => t.SymbolRuleId); // my example key


    foreach (var type in typeof(SymbolRule).GetDerivedClasses())
    {
        builder.HasDiscriminator()
               .HasValue(type, type.Name);
    }
}