实体框架自引用实体查询结果是扁平的和分层的

时间:2013-06-19 15:18:44

标签: entity-framework self-reference

我有一个自引用实体:

EF Mapping

当我查询这个实体时..

var query = this._context.DispositionPossibilities
    .Where(x => x.AreaID == areaID)
    .Where(x => x.IsActive == true);

..生成的集合包含从根查询返回的每个项目,然后具有ParentID的那些项目在子集合中被“复制”(由于导航属性)。

我可以通过这样做删除它们:

    // have to ToArray() first because the child entities will be excluded if I don't..
    rValue = query.ToArray();
    // trim off the entities at the root that shouldn't be there..
    rValue = rValue.Where(x => !x.ParentCode.HasValue).ToArray();

..但有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

<强> [编辑]
我下面的原始Include解决方案不会遍历整个层次结构。这对我来说应该是显而易见的,但它只会返回层次结构的第一级。

由于我每天最多会对每个树进行一次这样的调用,所以我会受到性能影响。

那就是说,我确实提出了一种更好的方法来剥离层次结构中的非根元素:

var subset = new List<DispositionPossibility>();
foreach (var disp in query.OrderBy(x => x.ParentCode).ToArray())
{
    if (!disp.ParentCode.HasValue)
        subset.Add(disp);
    else
        break;
}

这比我使用的第一种方法快<4> .7秒。 (所以几乎和Include方法一样好,但实际上给了我所有级别。) 添加ASC排序并突破循环,使我的27k项目树减少.1-.25秒。




[原创(BAD)答案]

在没有看到这一天并回到它之后,花了5秒钟才想到如何做到这一点。

var query = context.DispositionPossibilities
    .Include("ChildDispositions")
    .Where(x => x.AreaID == areaID)
    .Where(x => !x.ParentCode.HasValue)
    .Where(x => x.IsActive == true);

我运行了代码分析,这种方法几乎在所有情况下都表现得更好:
- 最值得注意的是我最大的树木有4个等级,约27,400个物品约为73到0.83秒。
- 对于小树(<5,000),差异远不那么明显(小于.01 - .05秒)