2012-03-28 2 views
0

NHibernate может загружать весь объект и связанные объекты в одном ударе db через подсказки в сопоставлении, если вы не используете разбитый на страницы запрос. Тем не менее, если вы используете пейджинг, он делает большое количество вызовов db.Как улучшить производительность Nhibernate при разбиении на страницы запросов по графу объектов

Например, у меня есть объект Invoice и объект InvoiceLine, так что у счета есть List строк фактуры. Плавное отображение Счет-фактура является

HasMany(x => x.Lines) 
    .Table("InvoiceLine") 
    .KeyColumn("InvoiceId") 
    .Fetch.Join() 
    .Not.LazyLoad(); 

Опция Not.LazyLoad отлично работает, чтобы загрузить весь граф объектов в одной БД попаданием при загрузке одного счета ... но если я хочу, чтобы запустить постраничного запрос типа

_invoiceQuery.Skip(200).Take(100); 

Тогда NHibernate сначала загружает все 100 счетов-фактур в один удар ... и затем попадает в базу данных более 100 раз за счет-фактура линий каждого счета-фактуры по одному за раз.

Есть ли способ, чтобы уменьшить это до 2 хитов, то есть

  1. Загрузки счета-фактуры
  2. нагрузок ВСЕХ InvoiceLines для счетов-фактур в (1)?

Я попытался вручную заставить проблему путем загрузки списка необходимых идентификаторов счетов в запрос, а затем с помощью

_invoiceQuery.Where(x => requiredIds.Contains(x.Id)); 

но мне кажется, NHibernate имеет те же проблемы при уменьшении Содержит ограничение в SQL ,

... или я должен признать, что мне нужно использовать другой инструмент?

ответ

0

По моему опыту, NHibernate не был отличным при использовании разбитых на страницы списков с нетерпением. Имейте в виду, в конечном счете ваши запросы выполняются как TSQL, возвращая кучу строк связанных данных. Теперь NHibernate способен преобразовать эти данные обратно в корневые объекты и связанные с ними дочерние элементы. Проблема в том, как мог NHibernate узнать до после, он вернул из БД сколько строк, которые ему нужно указать в своем TOP-заявлении, чтобы получить требуемый счет корневых объектов?

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

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

  1. Создать начальный запрос возвращающегося проекции указанных идентификаторов 100 счетов-фактур, а затем в отдельном попадании пойти и получить счета-фактуру, где их идентификаторы, содержащиеся в этом списке

  2. Создайте первоначальный запрос, возвращающий указанные 100 счетов (lazyload invoicelines), а затем в отдельном ударе извлекают счета-фактуры, в которых идентификатор счета-фактуры содержится в идентификаторах первого списка. Вы должны дважды ударить по базе данных и выйти замуж за родительские/дочерние сущности в коде.Будьте немного осторожны с ручной слиты лиц, хотя - если вы собираетесь делать какие-либо CRUD может быть стоит получить индивидуальную сущность свежий из БД первого

Если вы просто заинтересованы в отчетности представление данных (т. е. никаких операций CUD), возможно, подумайте о сопоставлении с пользовательским представлением db, а не

+0

Я не могу принять этот ответ, потому что «вы должны дважды ударить по базе данных и выйти замуж за родительские/дочерние сущности в коде «. неверно понимает последний вопрос в моем вопросе: NHibernate переводит '_invoiceQuery.Where (x => requiredIds.Contains (x.Id));' 100 раздельных удалений БД. – perfectionist