2017-02-23 225 views
0

我需要改变连接到使用NHibernate到左外连接的LINQ中。 我的代码看起来象NHibernate左连接LINQ

IQueryable<DimServicePoint> spq = 
          from sp in session.Query<DimServicePoint>() 
          join spm in session.Query<DimServicepointMeter>() on sp.ServicePointKey equals spm.ServicePointKey into gj 
          from subsp in gj.DefaultIfEmpty() 
          where (sp.ServicePointID == servicePointID && sp.DimAccount.AccountKey != 0 && sp.StartDayID <= currentDateId && sp.EndDayID >= currentDateId) 
          select sp; 

现在,我的要求是加入DimServicepointMeter左加入此查询。 等效SQL查询:

select * from dw.dim_servicepoint sp 
left join dw.dim_servicepoint_meter spm on sp.servicepointkey = spm.servicepointkey 
where sp.servicepointid = @ServicePointID and sp.accountkey != 0 
and sp.startdayid <= @currentDateId and sp.enddayid >= @currentDateId 

我没有太多工作在NHibenate或LINQ所以没有太多的想法怎么办左加入NHibernate的或LINQ。 任何帮助表示赞赏

+2

http://stackoverflow.com/a/15590126/1162077 –

回答

0

当前不支持任意左连接(v4.1)。他们翻译成LINQ GroupJoin,与一起使用时抛出NotImplementedException

正如answer中写的David所链接的那样,您可以改为使用。 Plain 也可以。

您可以改为将您的仪表映射到您的服务点上。它会看起来像(没有你的DimAccount属性):

public class DimServicePoint 
{ 
    public virtual int ServicePointID { get; set; } 
    public virtual int StartDayID { get; set; } 
    public virtual int EndDayID { get; set; } 
    public virtual int ServicePointKey { get; set; } 
    public virtual ISet<DimServicePointMeter> ServicePointMeters { get; set; } 
} 

public class DimServicePointMeter 
{ 
    public virtual int ServicePointMeterID { get; set; } 
    public virtual int ServicePointKey { get; set; } 
} 

映射有:

<class name="DimServicePoint"> 
    <id name="ServicePointID"> 
     <generator class="assigned" /> 
    </id> 
    <property name="StartDayID" /> 
    <property name="EndDayID" /> 
    <property name="ServicePointKey" /> 

    <set name="ServicePointMeters" inverse="true" batch-size="20"> 
     <key column="ServicePointKey" property-ref="ServicePointKey" /> 
     <one-to-many class="DimServicePointMeter" /> 
    </set> 
</class> 
<class name="DimServicePointMeter"> 
    <id name="ServicePointMeterID"> 
     <generator class="assigned" /> 
    </id> 
    <property name="ServicePointKey" /> 
</class> 

然后就可以用您的数据:

var spq = session.Query<DimServicePoint>() 
    .Where(sp => sp.ServicePointID == servicePointID && sp.DimAccount.AccountKey != 0 && 
     sp.StartDayID <= currentDateId && sp.EndDayID >= currentDateId); 

对查询结果访问.ServicePointMeters将最多收集20个加载的服务点集合,从而触发一个延迟加载的米集合。这是由于我建议的映射中的batch-size属性。没有它(并且没有全局配置的batch-size),它一次只会触发一个集合的延迟加载,可能导致n + 1性能问题。

如果你想急切地加载它们,而不是,只需添加获取:

var spq = session.Query<DimServicePoint>() 
    .Where(sp => sp.ServicePointID == servicePointID && sp.DimAccount.AccountKey != 0 && 
     sp.StartDayID <= currentDateId && sp.EndDayID >= currentDateId) 
    .FetchMany(sp => sp.ServicePointMeters); 

结果查询将使用一个左联接。

注:
我个人避免LINQ SQL的语法,我喜欢的LINQ扩展方法的使用,如我的回答说明。我发现它们更具可读性。
我赞成惰性加载加载NHibernate,因为它可以批量加载延迟加载。它倾向于在保持良好性能的同时简化代码,正如我已经解释过的here