2009-10-29 2 views
9

У меня есть странная проблема в моем текущем проекте. Ленивая загрузка запросов не работает. Когда я запрашиваю список, nhibernate извлекает все ассоциации отдельно.NHibernate создает прокси через session.Load(), но не через Linq или Criteria API

Я извлек небольшие его части и поместил их в отдельное решение. В основном то, что у меня есть сейчас, это таблица счетов и таблица AccountSync. Оба имеют идентификатор и URL-адрес, а идентификатор - только db-guid.

Мои классы:

public class HippoAccount 
{ 
    public virtual Guid Id { get; set; } 
    public virtual string Url { get; set; } 
    public virtual HippoAccountSync Sync { get; set; } 
} 

public class HippoAccountSync 
{ 
    public virtual Guid Id { get; set; } 

    public virtual string Url { get; set; } 
    public virtual HippoAccount Account { get; set; } 
} 

Когда я теперь загрузить объект через его справ:

var account = session.Load<HippoAccount>(accountId); 
Console.WriteLine(NHibernateUtil.IsPropertyInitialized(account, "Sync")) 

... она возвращает false и сама учетная запись является прокси.

Но при загрузке списка с помощью критериев API:

var account = (HippoAccount)session 
    .CreateCriteria(typeof (HippoAccount)) 
    .Add(Restrictions.Eq("Id", accountId)) 
    .List()[0]; 

... свойство Sync инициализируется (запуская второй запрос на выборку), а возвращаемый объект не является прокси-сервер.

Это поведение по умолчанию? Что я ошибаюсь?

отображение является:

<class name="HippoAccount" table="AllAccounts"> 
    <id name="Id" type="guid"> 
    <generator class="guid"/> 
    </id> 
    <property name="Url" /> 

    <many-to-one 
      class="HippoAccountSync" 
      name="Sync" 
      not-found="ignore" 
      property-ref="Url"> 
    <column name="url" /> 
    </many-to-one> 
</class> 

<class name="HippoAccountSync" 
     mutable="false" 
     table="Accounts"> 

    <id name="Id" type="guid"> 
    <generator class="guid"/> 
    </id> 

    <property name="Url"> 
    <column name="serviceUri" /> 
    </property> 

    <many-to-one class="HippoAccount" 
       name="Account" 
       property-ref="Url" 
       not-found="ignore"> 

    <column name="serviceUri" /> 
    </many-to-one> 

</class> 
+0

не уверен, если это полностью связаны, но есть проблемы с не-FOUND = "игнорировать": http://nhjira.koah.net/browse/NH-1001 http: //guildsocial.web703 .discountasp.net/dasblogce/CommentView, guid, ba00b19d-bd60-442b-b2e7-935277a9f1eb.aspx –

+0

Вы правы. Другой проблемой является свойство-ref - он также отключает ленивую загрузку. http://maonet.wordpress.com/2007/12/05/lazy-load-conflicts-with-property-ref-in-many-to-one-mapping/ –

ответ

10

После некоторых дополнительных исследований, я нашел ответы. Ответы, потому что есть много вещей, которые могут предотвратить ленивую загрузку в NHibernate.

  1. Запрос против Session.load: При получении товара через session.Load() вы получаете прокси. Но как только вы получаете доступ к любому объекту, скажем, Url, объект выбирается, включая все его ассоциации, которые не поддерживают ленивую загрузку.

  2. property-ref: Lazy loading работает только над объектами id. Когда свойство-ассоциация разрешается посредством другого столбца в целевом объекте, NH получает его с нетерпением. Не то, чтобы это не было бы возможно, это просто не реализовано: Bug

  3. не обретенной = «игнорировать» позволяет недопустимых внешних ключей, то есть, если упоминаемая сущность не найдена NH запустит свойство с нулевым значением. NH не перехватывает доступ к свойствам для ленивой загрузки, а вместо этого назначает прокси-объект. С not-found="ignore" он не может решить, должно ли свойство быть установлено в null или прокси для данного, возможно, недопустимого внешнего ключа. Это можно решить, перехватив доступ к ресурсу.

  4. При отключении not-found="ignore" и property-ref экспорт схемы будет создавать ограничения, обеспечивающие циклическую ссылку. Нехорошо! Тогда правильное сопоставление будет ограничено взаимно однозначным отношением, где ключ для HippoAccountSync должен иметь генератор foreign.

Ресурсы

+0

С session.Load() вы можете, конечно, безопасно получить доступ к свойству Id прокси-сервера без попадания в базу данных, так как вы дали прокси идентификатор для начала. – Jay

+0

ссылка на ошибку свойства-ref больше не существует, ошибка 404. Любая идея об этом прогрессе? – shanabus