实现包含子类的ICollection结构 [英] Materializing an ICollection structure containing subclasses

查看:120
本文介绍了实现包含子类的ICollection结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm reviewing some code that was written in the EF 4 days because it stands out during performance benchmarking.

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

The purpose of the code is to materialize an ICollection<MyBaseClass> using Entity Framework (we're now on EF 6.1).

之所以存在该代码,是因为检索时未实现特定子类中的引用

The code exists because references present in specific subclasses aren't materialized when retrieving

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

从数据库中,当存储的实际类型是MyBaseClass的子类时.

from the database, when the actual types stored are subclasses of MyBaseClass.

示例子类:

public SubA : MyBaseClass
{
    public virtual ICollection<Options> Ref1 { get; set; }
}

当前,代码执行以下操作:

Currently, the code does something like this:

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<MyBaseClass>() Base包含多个具体子类的混合. ICollection中通常有几百个对象.

Note that ICollection<MyBaseClass>() Base contains a mix of several concrete subclasses. There are generally a few hundred objects in the ICollection.

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

Is there a more efficient way to materialize Base?

推荐答案

如果性能会更好(无法执行(有时执行单个复杂查询,尤其是包含子集合的情况下,可能会产生负面影响)),这是无法预先说明的,但是您可以将数据库查询的数量减少到K,其中K是需要额外包含的子类类型的数量.

It cannot be said in advance if the performance will be better (sometimes executing a single complex query, especially with sub collection includes may have actually negative impact), but you can minimize the number of database queries to K, where K is the number of subclass types that need additional includes.

您需要将LoadSubclasses方法基于表示所有基础实体的IQueryable<TBase>,并使用OfType过滤器针对每种子类类型执行一个查询:

You need to base the LoadSubclasses method on IQueryable<TBase> representing all base entities, and execute one query per each subclass type using OfType filter:

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));

这篇关于实现包含子类的ICollection结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆