简体   繁体   English

如何在 EF Core 中自动执行 Map TPH 派生类?

[英]How to Automatically Map TPH Derived Classes in EF Core?

By default, EF6 would map a base abstract class and it's derived classes for Table Per Hierarchy (TPH).默认情况下,EF6 将 map 为基础抽象 class 及其为每个层次结构表 (TPH) 的派生类。

EF Core no longer follows this logic and requires derived classes to be opted in. The documentation states: EF Core 不再遵循此逻辑,并要求选择加入派生类。文档指出:

By convention, types that are exposed in DbSet properties on your context are included in the model as entities.按照惯例,在上下文的 DbSet 属性中公开的类型作为实体包含在 model 中。 Entity types that are specified in the OnModelCreating method are also included, as are any types that are found by recursively exploring the navigation properties of other discovered entity types.还包括在 OnModelCreating 方法中指定的实体类型,以及通过递归探索其他已发现实体类型的导航属性找到的任何类型。

Using this approach is not too hard to follow if you have a few sub-types as you can just add them as DbSets or add a HasDiscriminator().HasValue() for each sub-type with mapping as below:如果您有几个子类型,则使用这种方法并不难,因为您可以将它们添加为 DbSet 或为每个子类型添加 HasDiscriminator().HasValue(),映射如下:

builder.HasDiscriminator()
    .HasValue<CommaSymbolRule>("CommaSymbolRule")
    .HasValue<DashSymbolRule>("DashSymbolRule")
    .HasValue<IsNumericSymbolRule>("IsNumericSymbolRule")
    .HasValue<IsPunctuationSymbolRule>("IsPunctuationSymbolRule")
    .HasValue<PeriodSymbolRule>("PeriodSymbolRule")

In some circumstances this is a sub-optimal as you may have many derived classes.在某些情况下,这是次优的,因为您可能有许多派生类。 In my case, I have a rules engine and do not want to have map each rule individually.就我而言,我有一个规则引擎,不想让 map 每个规则单独使用。

Is there a way to automatically map the sub-types of a base class in an EF Core Table Per Hierarchy scenario without having to manually add them?有没有办法在 EF Core Table Per Hierarchy 场景中自动 map 基本 class 的子类型,而无需手动添加它们?

I thought there may be a way to do this in EF Core, but found that there was not one.我认为在 EF Core 中可能有一种方法可以做到这一点,但发现没有。

I discussed with the EF team why automatic opt-in is no longer the default and they gave concerns about the stability of "assembly scanning solutions" which are probably very valid.我与 EF 团队讨论了为什么自动选择不再是默认设置,他们对可能非常有效的“程序集扫描解决方案”的稳定性表示担忧。 They did not seem too interested in adding a new feature along those lines at this moment.目前,他们似乎对按照这些思路添加新功能不太感兴趣。

Here is what I came up with instead.这是我想出的。 It puts the assembly scanning in the mapping code but seems to work.它将程序集扫描放入映射代码中,但似乎有效。

First, I created an extension method to get the derived classes (which optionally can ignore particular types by name):首先,我创建了一个扩展方法来获取派生类(它可以选择按名称忽略特定类型):

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

Then use code similar to this for the base class in the EF Core mapping, switching out your type (ie: "SymbolRule" in this code):然后对 EF Core 映射中的基本 class 使用与此类似的代码,切换您的类型(即:此代码中的“SymbolRule”):

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

The foreach gets the derived classes from the base class and loops through them and adds a discriminator type for each. foreach 从基类 class 获取派生类,并遍历它们并为每个类添加一个鉴别器类型。

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

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