NHibernate создает прокси через session.Load(), но не через Linq или Criteria API.
-
10-07-2019 - |
Вопрос
У меня странная проблема в моем текущем проекте.Ленивая загрузка запросов не работает.Когда я запрашиваю список, nhibernate извлекает все ассоциации отдельно.
Я извлек небольшие его части и поместил в отдельный раствор.По сути, сейчас у меня есть таблица учетных записей и таблица синхронизации учетных записей.Оба имеют идентификатор и 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>
Решение
После еще нескольких исследований я нашел ответы.Ответы, потому что есть много вещей, которые могут предотвратить отложенную загрузку в NHibernate.
Запрос против.сеанс.Загрузка: При получении элемента через
session.Load()
вы получаете прокси.Но как только вы получите доступ любой собственность, скажем такUrl
, объект извлекается, включая все его ассоциации, которые не поддерживают отложенную загрузку.ссылка на свойство: Ленивая загрузка работает только с идентификатором объекта.Когда ассоциация свойств разрешается через другой столбец в целевой сущности, NH быстро извлекает ее. Не то чтобы это было невозможно, просто это не реализовано: Ошибка
не найден = игнорировать позволяет неверный внешние ключи, то есть, если объект, на который ссылается, не найден, NH инициализирует свойство с нулевым значением.NH не перехватывает доступ к свойству для отложенной загрузки, а вместо этого назначает прокси-сервер объекта.С
not-found="ignore"
он не может решить, должно ли свойство быть установлено в значение null или прокси для данного, возможно, недействительного внешнего ключа. Эту проблему можно решить, перехватив доступ к собственности.При отключении
not-found="ignore"
иproperty-ref
экспорт схемы создаст ограничения, обеспечивающие циклическую ссылку.Не хорошо!В этом случае правильным отображением будет ограниченное взаимно-однозначное отношение, где ключом кHippoAccountSync
должен быть генераторforeign
.
Ресурсы