即使您只迭代集合中的第一个项目,延迟加载是否会加载整个集合?或者它只加载在集合中迭代的项目?
...或者我不知道我在说什么?
答案 0 :(得分:5)
@Slauma的答案是正确的 - 第一次访问导航属性时会加载整个集合。它必须采用“普通”导航属性,因为该集合只是一个常规的ICollection<>而不是IQueryable<>。
但是,如果您不希望加载整个集合,则可以执行两项操作。如果您有可用的上下文,那么您可以使用Query方法真正加载懒惰。例如:
foreach (var role in context.Entry(user).Collection(e => e.Roles).Query())
{
Console.WriteLine(role.Name);
if (role.Name == "Role1")
break;
}
如果您事先知道要查找的实体,可以进一步了解这一点。例如,要加载Role1,您可以执行以下操作:
var role1 = context.Entry(user)
.Collection(e => e.Roles)
.Query()
.Single(r => r.Name == "Role1");
这篇文章提供了有关Query方法的更多细节:
如果您希望在运行查询时不需要上下文,那么请查看这些博客文章,解释如何制作超级惰性集合:
http://blog.oneunicorn.com/2011/03/28/extra-lazy-collection-count-with-ef-4-1-part-1/
以及更一般的IQueryable支持的集合:
http://blog.oneunicorn.com/2011/03/30/a-more-general-queryable-collection/
答案 1 :(得分:4)
当您开始迭代集合时,延迟加载会加载整个集合。示例:假设user
1的角色为“Role1”,“Role2”,“Role3”(user.Roles
为virtual
):
var user = context.Users.Single(u => u.Id == 1);
foreach (var role in user.Roles) // DB query happens here once
{
Console.WriteLine(role.Name);
if (role.Name == "Role1")
break;
}
虽然您永远不会访问Role2
和Role3
,但它们仍然已被加载。
答案 2 :(得分:1)
每次迭代可枚举的源时,它会迭代一次投影。