2009-07-07 12 views
12

Zadałem pytanie wcześniej o why left joins in Linq can't use defined relationships; do tej pory nie otrzymałem satysfakcjonującej odpowiedzi.Jak odszedłeś dołączyć do Linq, jeśli w złączeniu jest więcej niż jedno pole?

Teraz, na równoległym torze, zgodziłem się, że muszę używać słowa kluczowego join, jak gdyby nie było żadnej relacji między moimi obiektami i próbuję wyjaśnić, jak wyrazić moje zapytanie w Linq. Problem polega na tym, że jest to konglomerat lewych połączeń między wieloma tabelami, z wieloma polami związanymi z łączeniem. Nie ma mowy o uproszczenie tego, więc tutaj jest SQL w całej swej zdemaskowany chwały

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 

(FYI, jeśli pomaga zrozumieć, co próbuję zrobić: Próbuję ustalić, czy istnieją . TreatmentPlanDetail zapisy dla tego Patient gdzie zezwalający Payer wymaga recepty dla tego ServiceType, ale nie ma albo nie ServicePerscription rekord, albo wygasło)

teraz, oto co moim kod C# wygląda następująco:

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 }; 

Ups, nie kompiluje! Z jakiegoś powodu (chciałbym wyjaśnienia) nie mogę użyć tego dosłownie boolean wewnątrz equijoin! Dobrze, zostawię go i odfiltrować „RequiresPrescription” rzeczy później ...

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

... a teraz kompiluje - ale gdy uruchomię, otrzymuję „Odwołanie do obiektu nie ustawiony” wyjątek w tej linii. DUH! Oczywiście jest tam zerowy! Jak inaczej należy wykonać porównanie z lewostronnym, jeśli nie wolno ci odwoływać się do obiektu po prawej stronie, który może być pusty?

Jak zatem wykonać lewe połączenie przy użyciu wielu pól?

+1

Dla problemu boolowskiego, czy nie może to być problem z nazewnictwem (nic nie pasuje do "RxReq" po prawej stronie i nic nie pasuje do "RequestsPrescription" po lewej stronie)? Spróbuj nazywać boolean "RequestsPress" lub konkretnie nazwij prawą stronę pstr.RequiresPrescription "RxReq". –

Odpowiedz

14

Myślę, że trzeba użyć słowa kluczowego into i rozwiązać DefaultIfEmpty brakującej dzieci() po łączenia, a nie przed:

... 
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() jest prawdopodobnie stawili null ponieważ DataTable zwracane zawiera bez wierszy, powodując tym samym wyjątek. Uwaga: całe oświadczenie po in zostanie wykonane przed wyborem do niego, co nie jest pożądanym zachowaniem. Chcesz pasujące wiersze lub null, jeśli nie ma pasujących wierszy.


Dla logicznej problemu, to jest problem nazewnictwa (nic nie pasuje „RxReq” po prawej stronie i nic nie pasuje „RequiresPrescription” po lewej stronie). Spróbuj nazwać true "RequestsPress" tak jak powyżej (lub nazwij prawą stronę: "RxReq").

+3

... lub po prostu się poddaj, ocal swoje zdrowie psychiczne i używaj mikro ORM jak Dapper.net – niico