枚举在DbContext处理后成功

时间:2013-03-27 19:22:18

标签: entity-framework linq-to-entities

背景

我正在创建父/子关系的投影,其中包括父级的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]

这导致我this post,建议(in the comments)进行以下更改:

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,以便我可以枚举ChildIds,但是请点击F5,并且惊讶地看到代码有效。

问题

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

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

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