NHibernate создает прокси через session.Load (), но не через Linq или Criteria API - PullRequest
9 голосов
/ 29 октября 2009

У меня странная проблема в моем текущем проекте. Ленивая загрузка для запросов не работает. Когда я запрашиваю список, nhibernate извлекает все ассоциации отдельно.

Я извлек небольшие части и поместил их в отдельный раствор. В основном то, что я получил сейчас, это Account-Table и AccountSync-Table. У обоих есть идентификатор и 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; }
}

Когда я сейчас загружаю объект через его guid:

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>

1 Ответ

10 голосов
/ 30 октября 2009

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

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

  2. property-ref: Ленивая загрузка работает только над идентификатором объекта. Когда сопоставление свойств разрешается с помощью другого столбца в целевом объекте, NH охотно выбирает его. Не то чтобы это было невозможно, просто не реализовано: Ошибка

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

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

Ресурсы

...