【问题标题】:How to Automatically Map TPH Derived Classes in EF Core?如何在 EF Core 中自动映射 TPH 派生类?
【发布时间】:2021-01-21 00:03:38
【问题描述】:

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

EF Core 不再遵循此逻辑,并要求选择加入派生类。文档指出:

按照惯例,在您的 DbSet 属性中公开的类型 上下文作为实体包含在模型中。实体类型 还包括在 OnModelCreating 方法中指定的任何 通过递归探索导航找到的类型 其他已发现实体类型的属性。

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

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

在某些情况下,这是次优的,因为您可能有许多派生类。就我而言,我有一个规则引擎,不想单独映射每个规则。

有没有办法在 EF Core Table Per Hierarchy 场景中自动映射基类的子类型,而无需手动添加它们?

【问题讨论】:

    标签: c# entity-framework .net-core entity-framework-core discriminator


    【解决方案1】:

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

    我与 EF 团队讨论了为什么自动选择不再是默认设置,他们对可能非常有效的“程序集扫描解决方案”的稳定性提出了担忧。目前,他们似乎对按照这些思路添加新功能不太感兴趣。

    这是我想出的。它将程序集扫描放入映射代码中,但似乎可以工作。

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

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

    然后对 EF Core 映射中的基类使用与此类似的代码,切换您的类型(即:此代码中的“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);
        }
    }
    

    foreach 从基类中获取派生类并循环遍历它们,并为每个派生类添加一个鉴别器类型。

    【讨论】:

      猜你喜欢
      • 2010-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-20
      • 2015-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多