2017-02-23 298 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