2

背景

我正在从父/子关系创建一个投影,其中包括父级的 Name 属性和子级 ID 的列表。

代码

private class ParentChildInfo
{
    public string Name { get; set; }
    public List<int> ChildIds { get; set; }
}

var infos = ctx.Masters.Include(m => m.Children).Select(
    m => new ParentChildInfo()
    {
        Name = m.Name,
        ChildIds = m.Children.Where(c => c.SomeProp.StartsWith("SpecialValue"))
                    .Select(c => c.Id).ToList()
    }).ToList();

不幸的是,这产生了错误

LINQ to Entities 无法识别方法 'System.Collections.Generic.List`1[System.Int32] ToList[Int32]

这导致我这篇文章,其中建议(在评论中)进行以下更改:

private class ParentChildInfo
{
    public string Name { get; set; }
    public IEnumerable<int> ChildIds { get; set; } // No longer List<int>
}

var infos = ctx.Masters.Include(m => m.Children).Select(
    m => new ParentChildInfo()
    {
        Name = m.Name,
        ChildIds = m.Children.Where(c => c.SomeProp.StartsWith("SpecialValue"))
                    .Select(c => c.Id) // Dropped the .ToList()
    }).ToList();

我最初想要获取列表而不是可枚举,因为使用结果的代码会运行几分钟,而且我不想将 DbContext 占用那么长时间。

我使用这样的代码:

using (MyContext ctx = new MyContext())
{
    // code from above that populates infoes
}

foreach (var info in infoes)
{
    // use info.ChildIds
}

我计划将其foreach移入,using以便我可以枚举 ChildId,但改为按 F5 并惊讶地发现代码有效。

问题

鉴于 DbContext 在那一点被处置并且 ChildIds 是IEnumerable<int>而不是List<int>,为什么我可以枚举 ChildIds?

4

2 回答 2

3

这是因为查询ToList()infos实际执行查询。因此枚举集合ctx.Masters并填充预测。即使没有它,Include它也会注意到Master.Children已解决并发出 SQL 连接。的实现类型IEnumerable<int> ChildIds可能是List<int>.

于 2013-03-27T19:47:01.070 回答
1

您对查询执行了 .ToList() ,因此执行了查询并实现了所有结果,并且应该关闭与数据库的连接。我认为如果您没有 .ToList() 它将不起作用,因为(至少在 EF5 中)结果正在以流式方式处理,并且在请求时实体化(即在循环中的每次迭代中)。

于 2013-03-27T19:48:09.643 回答