4

Я работаю над проектом с богатой объектной моделью с различными наборами совокупных корней.Яркая загрузка ленивых загруженных объектов в nHibernate с использованием ActiveRecord

Мы используем Замок стек (монорельс до nHibernate с ActiveRecord).

Мы отметили совокупные корни как ленивые [ActiveRecord(Lazy = true)] и настроили поддельные подпрограммы в нашем репозитории, чтобы получить выборку графа объектов. Мы используем HQL для определения желаемых выборок из нашей дочерней коллекции нашего корня,

например. если Account - это совокупный корень (и отмеченный ленивым загруженным), мы будем получать выборки Account .. Order .. Product объектов для полного графика.

Так что никаких сюрпризов пока (надеюсь).

Теперь, если в приведенном выше примере Продукт также отмечен [ActiveRecord(Lazy = true)], это, похоже, остановит директиву fager fetch в HQL.

Кто-нибудь знает способ принудительного извлечения ленивого загруженного дочернего объекта ??

Приветствия Иэн

Update:

Ok вот несколько примеров HQL, используя пример из 'me.yahoo.com/../1' ниже, мы используем IMuliQuery для reslove N + 1 зависимостей при наборе отношений «многие ко многим». Мы также явно используем классы отображения многих-ко-многим. В результате наша HQL является:

from Account a 'm eager loading the graph 
inner join fetch a.AccountsOrders ao 
inner join fetch ao.Order 
from Account a 'm eager loading the graph 
inner join fetch a.AccountAddresses aa 
inner join fetch aa.Address ad 
where a.ID = ? 

... так что выполняет операторы 2 SQL и возвращает необходимый минимальный набор строк, и мы можем решить эту проблему вниз в один граф объектов. Ницца.

... Но если, скажем, Address был отмечен ленивым загружен (и Order не было), доступ к Order не влечет за собой дополнительные операторы SQL, но доступ к Address делает, несмотря на то, как охотно загружены.

Так почему же не ленивый загруженный объект Address, выше, нетерпеливый из приведенного выше утверждения?

+0

, пожалуйста, напишите hql –

+0

Он был решен с обновлением nHibernate. – penderi

ответ

0

Почему вы хотите нетерпеливый поведение?

Все атрибуты отношений в ActiveRecord имеют параметр «Lazy =», чтобы сообщить ActiveRecord о ленивой загрузке связанного объекта. Все, кроме BelongsTo. BelongsTo проверяет, имеет ли зависимый объект Lazy = true в свой атрибут ActiveRecord, а затем создает прокси для объекта вместо того, чтобы делать выбор или соединение.

Для ленивой загрузки для работы все методы и свойства экземпляра класса должны быть помечены как виртуальные.Это позволяет ActiveRecord создавать динамический класс прокси.

Теперь может показаться хорошей идеей получить полный график производительности, но на практике он, вероятно, медленнее. У меня есть 3 веские причины:

1.) BelongsTo имеет параметр Fetch, чтобы определить, как связаны объекты. FetchEnum.Join заставляет AR использовать Join. FetchEnum. Выберите команду AR для использования отдельных операторов выбора для каждого объекта. Совпадения медленны, мы видим улучшение производительности 10 раз от перехода к индивидуальным выборам. Между клиентским кодом между Lazy = true + FetchEnum.Select и eager нет существенной разницы в клиентском коде.

2.) NHibernate делает кеширование. Если объект уже кэширован в сеансе или в кеше уровня 2, он может быть загружен в форме и избежать дополнительной работы.

3.) Вы бы пропустили какие-либо преимущества ленивой загрузки в случаях, когда вы не ссылались на часть графика объекта. Снова вы бы сделали больше работы, чем необходимо.

+2

Я в целом согласен, но не согласен с необходимостью когда-либо нуждаться в нетерпеливом поведении .... По умолчанию, мы устанавливаем наши Lazy атрибуты, как требуется для «повседневного» использования наших объектов. Однако некоторые методы/процессы являются тяжелыми данными и, таким образом, мы получаем «большие графики» данных. Эти роли Fetch, которые у нас есть, имеют форму специфических потребностей и, как показано, являются более эффективными (более низкая частота SELECTS, видимых в NHProf и SqlProfiler). Так что в повседневных объектных операциях, конечно, мы полагаемся на отметку. Однако для тяжелых операций с данными мы будем выбирать из одного из кандидатов ролей. – penderi

1

Сделайте «внутреннюю попытку соединения» на объекте Account.Order.Product. Так что вместо того, чтобы что-то вроде этого (что вы, вероятно, уже есть):

"from Account a inner join fetch a.Order where a.ID = ?" 

рассказывайте для извлечения Order.Product, а также:

"from Account a inner join fetch a.Order inner join fetch a.Order.Product where a.ID = ?" 
+2

Почему это проголосовало? В тех случаях, когда желаемая загрузка желательна, не является ли это хорошим решением? Голосование до -2 с -3. – Andy

0

От "NHibernate в действии", стр 225:

NHibernate в настоящее время ограничивает вас выборку только одна коллекция с нетерпением.

Это может объяснить второй запрос на выбор адресов.