Двойная выборка NHibernate для несуществующих отношений «многие к одному» - PullRequest
2 голосов
/ 13 октября 2010

У меня есть сущность с несколькими отношениями «многие к одному», и я обнаружил, что могу охотно получить их в одном запросе, например:

public Accommodation GetEager(int id)
{
    IList<Accommodation> query = NHibernateSession.CurrentFor(NHibernateSession.DefaultFactoryKey)
        .CreateQuery(@"
        select a from Accommodation as a
        left join fetch a.AccommodationType
        left join fetch a.AccommodationUnitType
        left join fetch a.CollectionType
        where a.Id = :id
        ")
        .SetProperties(new {id})
        .SetCacheable(true)
        .List<Accommodation>();

    return query.SingleOrDefault();
}

Однако отношения не всегда существуют, и я определил сопоставления следующим образом:

mapping.References(x => x.AccommodationUnitType).NotFound.Ignore();

Я обнаружил, что когда отношения не существуют, NHibernate сгенерировал второй SQL-запрос для его поиска, предположительно потому, что обнаружил, что свойство имеет значение null.

Мой первый вопрос: как я могу предотвратить этот второй SQL-запрос?

Мой второй вопрос: есть ли более простой способ сделать выборку в одном запросе? Кажется очень простым поведением, что каждый хотел бы получить все в одном запросе, а не в отдельном запросе для каждого отношения многие-к-одному (что кажется поведением по умолчанию).

1 Ответ

1 голос
/ 13 октября 2010

Вы уверены, что используете NotFound().Ignore() правильно? Этот параметр определяет, что будет делать NHibernate при наличии недопустимого внешнего ключа. В этом случае NotFound().Ignore() предотвращает возникновение исключения EntityNotFoundException. С настройкой, если связанный объект не найден, тогда значение будет нулевым. Если у вас есть ссылочная целостность для этих отношений, вам не нужно NotFound().Ignore().

Поведение, которое вы видите, очевидно ожидаемое и хорошо известное и вряд ли изменится .

Что касается вашего второго вопроса, я бы посоветовал всегда начинать с поведения по умолчанию с отложенной загрузкой и только оптимизировать с энергичными нагрузками, необходимыми для реальных проблем производительности. Ленивая загрузка часто более эффективна, чем активное извлечение, потому что а) объект уже может быть в кеше (не требуется отключение дБ) и б) выбор по первичному ключу очень быстрый. Вполне возможно, что ваш запрос с тремя объединениями выполняется хуже, чем четыре выбора по первичному ключу.

...