【问题标题】:Materializing an ICollection structure containing subclasses实现包含子类的 ICollection 结构
【发布时间】:2017-08-21 00:14:39
【问题描述】:

我正在审查一些在 EF 4 天内编写的代码,因为它在性能基准测试中脱颖而出。

代码的目的是使用实体框架实现ICollection<MyBaseClass>(我们现在使用的是 EF 6.1)。

代码存在是因为特定子类中存在的引用在检索时没有具体化

public Parent
{
    public virtual ICollection<MyBaseClass>() Base { get; set; }
}

来自数据库,当实际存储的类型是 MyBaseClass 的子类时。

示例子类:

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
    }
}

请注意,ICollection&lt;MyBaseClass&gt;() Base 包含多个具体子类的混合。 ICollection中一般有几百个对象。

有没有更有效的方法来实现Base

【问题讨论】:

标签: entity-framework entity-framework-6


【解决方案1】:

不能提前说性能是否会更好(有时执行单个复杂查询,尤其是子集合包含实际上可能会产生负面影响),但是您可以将数据库查询的数量最小化到 K,其中 K 是需要额外包含的子类类型的数量。

您需要将LoadSubclasses 方法基于代表所有基本实体的IQueryable&lt;TBase&gt;,并使用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));

【讨论】:

  • 就我而言,这种方法要快 140 倍。
【解决方案2】:

对于那些使用 EF Core 2.1 或更高版本的用户,此功能is now supported 开箱即用。

2010 年的要求:

当实体框架的数据模型中具有导航属性时 除了什么时候,不可能急切加载该导航属性 使用 OfType 或当急切加载派生类型本身时 导航属性。

2018 年的回应:

该功能是 EF Core 2.1 的一部分,目前处于预览阶段。 如果您发现任何问题,请在我们的问题跟踪器中创建问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多