2010-09-01 4 views
1

Я пытаюсь выполнить LEFT OUTER JOIN с критериями nhibernate. У меня также есть фильтр, который применяется к моим запросам.Выполнение левого внешнего соединения при применении фильтра nhibernate

Проблема заключается в том, что фильтр останавливает левое внешнее соединение, работая должным образом, если результат объединения равен нулю.

В очень простом примере я хочу, чтобы вернуть все музыканты, и если они находятся в группе, то и их группа

NHibernate генерирует следующий SQL

SELECT this_.Name, band2_.Name 
FROM Musicians this_ 
     left outer join [Band] band2_ 
     on this_.BandID = band2_.ID 
WHERE (band2_.IsDeleted = 0) 

, который не будет возвращать если они не в группе. Я хочу что-то вроде

SELECT this_.Name, band2_.Name 
FROM Musicians this_ 
     left outer join [Band] band2_ 
     on this_.BandID = band2_.ID 
WHERE this_.ID = 4894 /* @p3 */ 
     (band2_.ID IS NULL OR band2_.IsDeleted = 0) 

Возможно ли это с nhibernate?

UPDATE

var projections = new[] 
       { 
        Projections.Property("Musician.Name").As("MusicianName"), 
        Projections.Property("Band.Name").As("BandName") 
       }; 

      return this.sessionProvider.GetSession().CreateCriteria<Musician>("Musician") 
       .CreateCriteria("Musician.Band", "Band", JoinType.LeftOuterJoin) 
       .SetProjection(projections) 
       .Add(Restrictions.Eq("Musician.ID", parameters.MusicianId)) 
       .SetResultTransformer(Transformers.AliasToBean<MusicianDetailsResult>()) 
       .UniqueResult<MusicianDetailsResult>(); 

Фильтр определяется с FluentNHibernate

this.WithName(FilterName).WithCondition("IsDeleted = 0") 
+0

Можете ли вы опубликовать код ICriteria? – DanP

ответ

0

Во-первых, это гораздо проще, если вы просто карта Бэнд музыканту в качестве ссылки:

public class MusicianDbMap : ClassMap<Musician> 
{ 
    public MusicianDbMap() 
    { 
     ... 
     References(x => x.Band) 
      .Nullable() 
      .Not.LazyLoad(); // Or lazy load... either way 
    } 
} 

Тогда вы можете просто запустить простой запрос - здесь он находится в L Inq-2-NHibernate:

Session.Linq<Musician>() 
     .Where(x => x.Band == null || !x.Band.IsDeleted) 
     .ToList(); 

Во-вторых, я не уверен, что это заявление твоего: «которые не будут возвращаться музыканты, если они не находятся в группе» ... Я не если это правильно. Левое внешнее соединение должно возвращать все строки, независимо от того, находятся они в группе или нет - вы уверены, что не сделали ошибку где-то еще?

+0

Музыкант отображается в качестве ссылки. Если вы посмотрите на sql, который генерирует nhibernate, фильтр, который применяется (band2_.IsDeleted = 0), останавливает музыкантов без возвращения групп (несмотря на левое соединение). если вы добавите проверку IS NULL, то она работает так, как я хочу. –

1

Это bug in NHibernate.

Я использовал предложенное обходное решение и установил useManyToOne на фильтр на false. Это свойство в настоящее время отсутствует в FluentNhibernate, поэтому я просто делаю это в ExposeConfiguration

foreach (var key in cfg.FilterDefinitions.Keys) 
{ 
    filter = cfg.FilterDefinitions[key]; 
    cfg.FilterDefinitions[key] = new FilterDefinition(
    filter.FilterName, 
    filter.DefaultFilterCondition, 
    filter.ParameterTypes, false); 
} 
Смежные вопросы