我之前问了一个关于why left joins in Linq can't use defined relationships的问题;到目前为止,我还没有得到满意的答复。
现在,在平行轨道上,我已经接受了我需要使用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!当然那里有一个空位!如果你不允许引用右侧的对象,那么你应该如何与左连接进行比较呢?这可能是空的?
那么,您应该如何使用多个字段进行左连接?
答案 0 :(得分: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”)。