2010-09-01 62 views
1

我試圖用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 2010-09-01 13:45:19

回答

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

音樂家被映射到樂隊作爲參考。 如果您查看nhibernate生成的sql,則應用的過濾器(band2_.IsDeleted = 0)會阻止音樂家沒有返回樂隊(儘管左連接)。如果您添加IS NULL檢查,那麼它可以按我的需要工作。 – 2010-09-01 15:06:49

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); 
}