在每个类型继承方案的表中加载 EF 导航属性

Posted

技术标签:

【中文标题】在每个类型继承方案的表中加载 EF 导航属性【英文标题】:Load EF navigation property in a Table per Type Inheritance scenario 【发布时间】:2014-05-14 16:30:07 【问题描述】:

我有一个与this question 非常相似的场景,但我正在尝试做一些更复杂的事情。

回顾一下,我基本上有一个案例列表,每个案例都有不同的类型:

Case -> CaseA
Case -> CaseB
Case -> CaseC

每个派生的Case 类都有一个或多个我需要包含的导航属性:

Case -> CaseA -> Employee
Case -> CaseB -> List<Something>
Case -> CaseC -> List<SomethingElse>

现在,我当然可以做一个大量的switch 声明,但我正在寻找这样的聪明东西:

foreach(var myCase in ListOfCases) 

    context.LoadAll(myCase); // <- THIS!
    context.Entry(myCase).LoadAllProperties() // <- OR THIS...
    // etc. etc.

当然,这些方法不存在,所以我想知道是否有人遇到过类似的问题,以及有什么好的和聪明的方法来解决它。

谢谢!

【问题讨论】:

您如何一次查询所有这些不同的案例类型?如果您查询基本案例,则它无权访问子案例的成员。 嗨代理,这正是我要解决的问题... :/ 在基础中有一个方法被子项覆盖并使用一些子项字段... 我认为您必须按类型加载每个案例,例如在引用的问题中。 AKA,一个大开关,但在上下文类中的一个函数中。 【参考方案1】:

最终解决方案非常简单:什么都不做! :)

基本上,如果对象层次结构设置正确并且导航属性(和集合)都具有virtual 修饰符以便可以启用LazyLoading,EF 将自行深入对象层次结构以加载在第一个SELECT期间没有加载:

 public CasesDbContext() 
     Configuration.LazyLoadingEnabled = true;
     Configuration.ProxyCreationEnabled = true;
 

然后例如这是方法:

var result = new List<CaseViewModel>();
var cases = _casesRepository.All;
foreach (var customCase in cases) 
    result.Add(new CaseViewModel() 
        Complete = customCase.IsComplete(), // <- at this point, the customCase is
                                            // the derived implementation
                                            // but the full hierarchy is missing
    );

这是一个示例派生类:

public class CaseB : Case 
    public int ReferenceId  get; set; 
    public virtual Reference Reference  get; set;  // <- "virtual" here is important!

    protected override bool IsComplete() 
        return Reference.Name == "Tallmaris"; // <- at this point the EF 
                                              // will load the Reference.
    

另一个需要注意的是,在遍历一组实体时加载引用可能会产生类似There is already an open DataReader associated with this Command which must be closed first 的错误。解决方案是在迭代之前使用ToList(),或者在连接字符串中启用MultipleActiveResultSets(感谢@Ladislav for his answer here)。

【讨论】:

以上是关于在每个类型继承方案的表中加载 EF 导航属性的主要内容,如果未能解决你的问题,请参考以下文章

EF 4.2 和继承的类关联属性的几个问题

如何在代码中首先在 TPT(每种类型的表)继承中启用级联删除?

在 MySQL 中实现继承:备选方案和只有代理键的表

Django:在使用模板继承时在基本模板文件中加载自定义过滤器时出现问题

如何在模块中加载未知类?

无法在 django 中加载引导导航栏(可能是明显的解决方案)