延迟加载在迭代时加载整个集合

本文关键字:集合 加载 迭代 延迟加载 | 更新日期: 2023-09-27 18:25:40

即使只迭代集合中的第一个项,延迟加载也会加载整个集合吗?还是只加载集合中迭代的项?

还是我不知道自己在说什么?

延迟加载在迭代时加载整个集合

@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");

这篇文章提供了更多关于查询方法的细节:

http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx

如果你想让这更具交易性,这样你就不需要在运行查询时提供上下文,那么看看这些博客文章,它们解释了如何制作额外的懒惰集合:

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/

当您开始迭代集合时,Lazy加载会加载整个集合。示例:假设user 1具有角色"Role1"、"Role2"、"rol3"(user.Rolesvirtual):

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;
}

尽管您从未访问过Role2Role3,但它们已被加载。

每次迭代源可枚举对象时,它都会迭代投影一次。