实现包含子类的ICollection结构

时间:2017-08-21 00:14:39

标签: entity-framework entity-framework-6

我正在审核一些在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 } }

2 个答案:

答案 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的一部分,目前正在预览中。   如果您发现任何问题,请在我们的问题跟踪器中创建问题。