12

先ほど、Linqの左結合で定義された関係を使用できない理由について質問しました。今日まで、私は満足のいく反応を得ていません。

現在、並行してjoin、オブジェクト間に関係が定義されていないかのようにキーワードを使用する必要があることを受け入れ、Linqでクエリを表現する方法を模索しています。問題は、複数のテーブル間の左結合の集合体であり、結合に複数のフィールドが含まれていることです。これを単純化する方法はないので、マスクされていない栄光のSQLを次に示します。

select *
from TreatmentPlan tp
join TreatmentPlanDetail tpd on tpd.TreatmentPlanID = tp.ID
join TreatmentAuthorization auth on auth.TreatmentPlanDetailID = tpd.ID
left join PatientServicePrescription rx on tpd.ServiceTypeID = rx.ServiceTypeID
left join PayerServiceTypeRules pstr on auth.PayerID = pstr.PayerID and tpd.ServiceTypeID = pstr.ServiceTypeID and pstr.RequiresPrescription = 1
where tp.PatientID = @PatientID

(参考までに、私がやろうとしていることを理解するのに役立つ場合:承認に処方箋が必要なTreatmentPlanDetailレコードがあるかどうかを特定しようとしていますが、レコードがないか、有効期限が切れています。 )。PatientPayerServiceTypeServicePerscription

さて、これが私のC#コードがどのように見えるかです:

var q = from tp in TreatmentPlans
        from tpd in tp.Details
        from auth in tpd.Authorizations
        join rx in ServicePrescriptions.DefaultIfEmpty() on tpd.ServiceTypeID equals rx.ServiceTypeID
        // from pstr in auth.Payer.ServiceTypeRules.DefaultIfEmpty() -- very frustrating that this doesn't work!!
        join pstr in LinqUtils.GetTable<PayerServiceTypeRules>().DefaultIfEmpty()
        on new { auth.PayerID, tpd.ServiceTypeID, RxReq = (bool)true } equals new { pstr.PayerID, pstr.ServiceTypeID, pstr.RequiresPrescription }
        select new { Payer = auth.Payer, Prescription = rx, TreatmentPlanDetail = tpd, Rules = pstr };

おっと、コンパイルしません!何らかの理由で(説明が欲しい)、その文字通りのブール値を等結合内で使用することはできません!いいでしょう、私はそれを省き、後で「RequiresPrescription」のものを除外します...

...
join pstr in LinqUtils.GetTable<PayerServiceTypeRules>().DefaultIfEmpty()
on new { auth.PayerID, tpd.ServiceTypeID } equals new { pstr.PayerID, pstr.ServiceTypeID }
...

...そしてコンパイルされます-しかし、実行すると、この行で「オブジェクト参照が設定されていません」という例外が発生します。 DUH! もちろん、そこにはヌルがあります!右側のオブジェクトを参照することが許可されていない場合、左側の結合との比較を他にどのように実行することになっていますか?それは潜在的にnullである可能性がありますか?

では、複数のフィールドを使用して左結合をどのように行うのでしょうか。

4

1 に答える 1

15

キーワードを使用して、結合前ではなく、結合intoに欠落している子のDefaultIfEmpty()を解決する必要があると思います。

...
join pstr in LinqUtils.GetTable<PayerServiceTypeRules>()
on new { auth.PayerID, tpd.ServiceTypeID, bool RequiresPrescription = true } 
equals new { pstr.PayerID, pstr.ServiceTypeID, pstr.RequiresPrescription } 
into pstrs
from PSTR in pstrs.DefaultIfEmpty()
select new { 
    Payer = auth.Payer, 
    Prescription = rx, 
    TreatmentPlanDetail = tpd, 
    Rules = PSTR 
};

LinqUtils.GetTable<PayerServiceTypeRules>().DefaultIfEmpty()返されるDataTableに行が含まれていないため、おそらくnullが返され、例外が発生します。後のステートメント全体inが、選択する前に実行されることに注意してください。これは、望ましい動作ではありません。一致する行が必要です。一致する行が存在しない場合はnullが必要です。


ブール問題の場合、これは命名の問題です(右側の「RxReq」に一致するものはなく、左側の「RequiresPrescription」に一致するものはありません)。上記のように「RequiresPrescription」に名前を付けてみてくださいtrue(または右側のpstr.RequiresPrescription「RxReq」に名前を付けてください)。

于 2009-07-07T17:17:46.993 に答える