背景
我正在创建父/子关系的投影,其中包括父级的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?
答案 0 :(得分:3)
这是因为ToList()
查询的infos
实际执行了查询。因此,枚举集合ctx.Masters
并填充投影。即使没有Include
,它也会注意到Master.Children
已被寻址并发出SQL连接。 IEnumerable<int> ChildIds
的实施类型可能是List<int>
。
答案 1 :(得分:1)
您对查询执行了.ToList(),以便执行查询并实现所有结果,并且应关闭与数据库的连接。我认为如果你没有.ToList(),因为(至少在EF5中)结果是以流方式处理的,并且实体在被请求时(即在循环中的每次迭代中)实现。