我正在审核一些在EF 4天内编写的代码,因为它在性能基准测试期间脱颖而出。
代码的目的是使用实体框架(我们现在使用的是EF 6.1)实现Reader e a
。
代码存在,因为在检索
时,特定子类中的引用未实现Identity
从数据库中,当存储的实际类型是MyBaseClass的子类。
示例子类:
Identity
目前,代码执行如下操作:
ICollection<MyBaseClass>
请注意public Parent
{
public virtual ICollection<MyBaseClass>() Base { get; set; }
}
包含几个具体子类的混合。 public SubA : MyBaseClass
{
public virtual ICollection<Options> Ref1 { get; set; }
}
中通常有几百个对象。
是否有更有效的方法来实现var parent = ctx.Parents.Include(p => p.Base).Where(...).Single();
LoadSubclasses(parent.Base);
...
private void LoadSubclasses(IEnumerable<MyBaseClass> myBase)
{
foreach (var my in myBase)
{
if (my is SubA)
{
this.Entry(my).Reference("Ref1").Load();
this.Entry((SubA)my).Ref1).Collection("Options").Load();
}
else... // Similar for other subclasses
}
}
?
答案 0 :(得分:3)
如果性能会更好(有时执行单个复杂查询,尤其是子集合包含可能实际上有负面影响),则不能提前说出来,但是您可以将数据库查询的数量最小化到K,其中K是需要额外包含的子类类型的数量。
您需要将LoadSubclasses
方法基于代表所有基本实体的IQueryable<TBase>
,并使用OfType
过滤器为每个子类类型执行一个查询:
private void LoadSubclasses(IQueryable<MyBaseClass> baseQuery)
{
// SubA
baseQuery.OfType<SubA>()
.Include(x => x.Ref1.Options)
.Load();
// Similar for other subclasses
}
您的样本的用法是:
var parent = ctx.Parents.Include(p => p.Base).Where(...).Single();
LoadSubclasses(ctx.Entry(parent).Collection(p => p.Base).Query());
或更一般地说:
var parentQuery = ctx.Parents.Where(...);
var parents = parentQuery.Include(p => p.Base).ToList();
LoadSubclasses(parentQuery.SelectMany(p => p.Base));
答案 1 :(得分:0)
对于EF Core 2.1或更高版本的用户,此功能is now supported开箱即用。
2010年的要求:
当在实体框架的数据模型中具有导航属性时 除了当时的导航属性,它并不具备令人兴奋的负载 使用OfType&lt;&gt;或者当急切地通过a加载派生类型本身时 导航属性。
2018年回应:
该功能是EF Core 2.1的一部分,目前正在预览中。 如果您发现任何问题,请在我们的问题跟踪器中创建问题。