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

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

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

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

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

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

4 ответа

Решение

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

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

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

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

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

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

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>();

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

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

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

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

Если это HQL, вы можете использовать join fetch чтобы получить ассоциацию с нетерпением.

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

Другие вопросы по тегам