NHibernate Ленивое Поведение Загрузка - PullRequest
2 голосов
/ 07 декабря 2011

Я читал эту статью о Nhibernate Lazy Загрузка http://nhforge.org/wikis/howtonh/lazy-loading-eager-loading.aspx, и он использует и пример структуры класса, подобной этой:

Class Diagram

В статье затем показываетсяследующий код:

using (ISession session = SessionFactory.OpenSession())
{
    var fromDb = session.Get<Order>(_order.Id);
    int sum = 0;
    foreach (var line in fromDb.OrderLines)
    {
        // just some dummy code to force loading of order line
        sum += line.Amount;
    } 
}

Затем мы поговорим о:

проблема выбора операторов n + 1.Если мы получим доступ к позициям строки заказа после загрузки заказа, мы создадим оператор выбора для каждой позиции, к которой мы обращаемся.

Это поведение, которое я запомнил при ленивой загрузке, а именно, когда я впервые получаю заказ,коллекция строк заказа - это прокси набора строк заказа, затем, когда я перебираю строки заказа, каждая из них загружается по требованию.

Однако это не то поведение, которое я наблюдаю.Что происходит, когда я пытаюсь сделать это в моем приложении, так это то, что, когда я получаю заказ, достаточно точно, чтобы коллекция строк заказа была прокси-сервером, но как только я получаю доступ к первому OrderLine, используя:

fromDb.OrderLines.First()

Вся коллекциязагружается в памятьЭто проблема для меня, так как коллекция содержит много элементов, и я хочу только поменять один, но если я загружаю все элементы в память, изменяю один и пытаюсь сохранить порядок, я, очевидно, получаю очень низкую производительность.

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

1 Ответ

4 голосов
/ 07 декабря 2011

"проблема выбора операторов n + 1. Если мы получим доступ к позициям строки заказа после загрузки заказа, мы сгенерируем оператор выбора для каждой позиции, к которой у нас есть доступ."не является основным.Строки заказа все загружаются вместе, потому что это в большинстве случаев гораздо эффективнее.Выбор N + 1 - это в основном код, подобный следующему:

var orders = session.QueryOver<Order>().List()

var usersWithOrders = orders.Select(o => o.User);

, поскольку у вас есть 1 Выбор для заказов и N Выбор для каждого пользователя (в действительности только для отдельных пользователей из-за кэша сеанса)

Если вы знаете, что у вас есть большие коллекции, и вы хотите обрабатывать только некоторые из них или вам требуется Count и Contains, тогда существует <bag lazy="extra"> / HasMany(x => x.Lines).ExtraLazyLoad(), в результате чего прокси-сервер коллекции отправляет запросы на Count, Contains, вместо этого вместо этого []все.

Или вы можете session.QueryOver<OderLines>().Where(line => line.Order == order && ...), чтобы получить конкретные строки, которые вы хотите обработать

...