Может ли NHibernate решить N + 1 без использования пакетной обработки или Criteria API для отношений Заказ -> Клиент? - PullRequest
1 голос
/ 18 марта 2011

Я читал и смотрел вокруг, чтобы найти этот ответ в черно-белом варианте.

Давайте поговорим о знакомой проблеме Customer и Order.Допустим, я загружаю 100 заказов, и каждый заказ связан с одним и только одним клиентом.

Используя Fluent NHibernate, я буду использовать References(), чтобы связать свои Order с Customer, и ятакже определит мои Not.LazyLoad() и Fetch.Join().

Теперь я думаю, гипотетически, NHibernate может просто объединить эти две таблицы и будет довольно легко гидрировать сущности.Однако в моих тестах я всегда вижу N + 1 запросов (на самом деле, возможно, только уникальные идентификаторы).Я могу поделиться своим кодом и таблицами, но это может утомить вас, поэтому

  • Можно ли преодолеть N + 1 для Заказа -> Клиент (один -> один или, скорее, Много -> Один)?Или я должен использовать пакетный API или Criteria API?
  • Если возможно, можете ли вы указать мне пример использования Fluent NHibernate?

Ответы [ 4 ]

2 голосов
/ 18 марта 2011

Часто жалуются, что fetch = "join" не работает .Это потому, что это не рассматривается HQL.Вы можете объявить это в HQL.

Я использовал fetch = "join", надеясь улучшить производительность, но во многих случаях прекратил его использовать.Проблема заключалась в том, что при соединении со многими таблицами SQL-сервер мог работать с максимальным количеством столбцов.В некоторых случаях вам вообще не нужны данные, и поэтому не очень полезно указывать их глобально в файле сопоставления.

Поэтому я бы рекомендовал

  • либо использоватьявная выборка соединений в HQL, потому что там вы знаете, действительно ли используются данные.
  • или для любого другого случая, пакеты являются отличным решением, потому что они прозрачны (о вашем коде не нужно знать), используют ленивую загрузку и одновременно уменьшают проблему N + 1.
2 голосов
/ 19 марта 2011

Привет
Есть два способа решения вашей проблемы

а) Использование критерия запроса Это будет выглядеть примерно так

Session.CreateQuery(typeof(Order))
.Add(<Restrictions if any>)
.SetFetchMode("Customer",FetchMode.Eager)
.List<Order>();

б) Использование HQL

Session.CreateQuery("select o from Order inner join fetch o.Customer where <conditionifany>").List<Order>();

Надеюсь, это поможет ..

2 голосов
/ 18 марта 2011

Я бы не смотрел на отображение столько, сколько на фактические запросы, которые вы делаете.Я оставляю ВСЕ свои сопоставления как LazyLoad по умолчанию и перезаписываю при необходимости.

Я использую Criteria API для запросов и использую CreateAlias ​​для объединения других таблиц по мере необходимости.NHProf настоятельно рекомендуется находить и устранять подобные ситуации.

0 голосов
/ 20 марта 2011

Какой API запросов вы используете?

Если это HQL, вы можете использовать join fetch для быстрого поиска ассоциации.

Для LINQ и QueryOver используйте .Fetch()

...