Ленивая загрузка загружает всю коллекцию после итерации? - PullRequest
1 голос
/ 25 февраля 2012

Ленивая загрузка загружает всю коллекцию, даже если вы перебираете только первый элемент в коллекции? Или он загружает только элементы, которые повторяются в коллекции?

... или я понятия не имею о чем говорю?

Ответы [ 3 ]

5 голосов
/ 27 февраля 2012

@ 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/

4 голосов
/ 25 февраля 2012

Ленивая загрузка загружает всю коллекцию, когда вы начинаете перебирать коллекцию. Пример: Предположим, что user 1 имеет роль «Role1», «Role2», «Role3» (user.Roles is 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, тем не менее они были загружены.

1 голос
/ 25 февраля 2012

Он перебирает проекцию один раз каждый раз, когда он перебирает перечисляемый источник.

...