2009-07-07 65 views
12

我剛纔問了一個關於why left joins in Linq can't use defined relationships的問題;迄今爲止我還沒有得到滿意的答覆。如果連接中有多個字段,你如何在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記錄這個Patient在授權Payer需要這個ServiceType處方,但要麼沒有ServicePerscription記錄,或者已經過期)

現在,這裏是我的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 }; 

糟糕,不編譯!出於某種原因(我想要一個解釋),我不能在equijoin中使用這個文字布爾值!好吧,我會離開它,並篩選出了「RequiresPrescription」的東西后...

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

...現在它編譯 - 但是當我跑,我得到一個「對象未設置」這條線上的例外。 DUH!當然,那裏是空的!如果您不允許在右側引用該對象,那麼您還應該如何執行與左連接的比較,那可能是空的?

那麼,你應該如何使用多個字段進行左連接?

+1

對於布爾問題,它不能是一個命名問題(右側沒有任何匹配的「RxReq」,沒有匹配左側的「RequiresPrescription」)?嘗試命名布爾型「RequiresPrescription」或專門命名右側的pstr.RequiresPrescription「RxReq」。 – 2009-07-07 16:58:11

回答

14

我認爲你需要使用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中返回包含可能是打開了一個空沒有行,從而導致你的異常。注意in之後的整個陳述將在選擇之前執行,這不是您想要的行爲。你想要匹配的行,或者如果沒有匹配的行存在,則返回null。


對於布爾問題,這是一個命名問題(沒有「RxReq」匹配右側並沒有什麼左側「RequiresPrescription」匹配)。嘗試命名true「RequiresPrescription」(如上所述)(或將右邊的pstr.RequiresPrescription「RxReq」命名)。

+3

...或者放棄,保存您的理智,並使用像Dapper.net這樣的微型ORM – niico 2016-05-09 20:07:19