Принудительный выбор в NHibernate - PullRequest
9 голосов
/ 15 декабря 2009

Я пытаюсь охотно получать коллекции, используя выборки, но все, что я есть получение внутренний присоединения. Что происходит?

Session.CreateCriteria(typeof(Foo))
    .SetFetchMode("Bars", FetchMode.Select)
    .CreateAlias("Bars", "b")
    .SetFetchMode("b.Bazes", FetchMode.Select)
    .List();

Я пытался изменить FetchMode на Eager, но это не работает - я по-прежнему получать внутренние объединения вместо отдельных выборок. Я не уверен, откуда он вообще получает внутреннее соединение, потому что в документации ничего не говорится о том, что FetchMode вызывает внутренние соединения. Можно ли получить нетерпеливый выбор?

Обновление Хорошо, я понял, что создание псевдонима вызывает внутреннее соединение. Поэтому я могу использовать .CreateAlias ​​("Bars", "b", JoinType.None), но тогда выборка b.Bazes возвращается к отложенной загрузке. Urgh.

Ответы [ 3 ]

1 голос
/ 05 ноября 2010

Для nhibernate для загрузки объектов используется левое внешнее соединение. Поэтому вам нужно изменить свой код следующим образом:

Session.CreateCriteria(typeof(Foo))
.SetFetchMode("Bars", FetchMode.Select)
.CreateAlias("Bars", "b", JoinType.LeftOuterJoin)
.SetFetchMode("b.Bazes", FetchMode.Select)
.List();

Это помогло мне в подобном сценарии .

1 голос
/ 15 декабря 2009

INNER JOIN - это то, как NHibernate будет загружать ваши записи и связанные с ними дочерние записи. Как правило, это наиболее эффективный способ сделать это.

Если использовать несколько операторов SELECT, тогда запрос для детей должен каким-то образом включать критерии для родителя. ВНУТРЕННЕЕ СОЕДИНЕНИЕ позволяет легко получить только связанных потомков, NHibernate правильно разделит это на несколько объектов после выполнения запроса.

Я полагаю, что Entity Framework 4 позволит вам выполнять несколько запросов и «волшебным образом» повторно присоединять связанные объекты, но я не знаю, что NHibernate имеет такую ​​функцию (я уверен, что кто-то исправит меня, если я ошибаюсь на этом).

0 голосов
/ 15 декабря 2009
Session.CreateCriteria(typeof(Foo))
   .SetFetchMode("Bars", FetchMode.Select)
   .CreateAlias("Bars", "b")  <-- this line triggers a join ( think )
   .SetFetchMode("b.Bazes", FetchMode.Select) 
   .List();

Если вы действительно не хотите объединений, вы можете указать fetch = "select" в отображении, но это приведет к выбору N + 1, что не рекомендуется (один выбор для каждого объекта Foo, а затем один для каждого Baze)

...