我之前问过一个关于 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
记录,其中授权 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 中使用那个文字 bool 值!好吧,我会把它留下来,稍后再过滤掉“RequiresPrescription”的东西......
...
join pstr in LinqUtils.GetTable<PayerServiceTypeRules>().DefaultIfEmpty()
on new { auth.PayerID, tpd.ServiceTypeID } equals new { pstr.PayerID, pstr.ServiceTypeID }
...
...现在它可以编译了——但是当我运行时,我在这一行得到了一个“未设置对象引用”的异常。 DUH! 当然里面有一个空值!如果您不允许引用右侧的对象,您还应该如何执行与左连接的比较,该对象可能为空?
那么,您应该如何使用多个字段进行左连接?
最佳答案
我认为您需要使用 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。
对于boolean问题,是一个命名问题(右侧没有匹配“RxReq”,左侧没有匹配“RequiresPrescription”)。尝试命名 true
“RequiresPrescription”,如我上面所说(或将右侧的 pstr.RequiresPrescription
命名为“RxReq”)。
关于c# - 如果联接中有多个字段,您如何在 Linq 中离开联接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1093494/