在每个类型继承的表场景中加载EF导航属性
本文关键字:加载 EF 属性 导航 类型 继承 | 更新日期: 2023-09-27 18:03:34
我有一个非常类似于这个问题的场景,但我正试图做一些更复杂的事情。
回顾一下,我基本上有一个案例列表,每个案例都有不同的类型:
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.
}
当然,这些方法并不存在,所以我想知道是否有人曾经有过类似的问题,什么可能是一个很好的和聪明的方法来解决它。
谢谢!
最后的解决方案真的很简单:什么都不做!:)
基本上,如果对象层次结构设置正确,导航属性(和集合)都有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在这里的答案)。