在应用nhibernate过滤器时执行左外连接

问题描述:

我试图用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

首先,这是如果你简单地映射乐队为音乐人作为参考更容易:

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

这是一个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); 
}