2017-02-23 4 views
0

NHibernateを左外部結合に使用しているlinqでjoinを変更する必要があります。 この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でリンクされている場合は、代わりにを使用できます。平野もそうです。

代わりに、サービスポイントにメーターをマッピングすることができます。それは希望(あなた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)、一度に1つのコレクションのみの遅延負荷が発生し、パフォーマンス上の問題が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を説明したように、良いパフォーマンスを維持しながらコードを単純化する傾向があります。

関連する問題