如果加入中有多个字段,你如何离开加入Linq?

Sha*_*ica 12 c# linq join left-join linq-to-sql

我之前问了一个问题,为什么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
Run Code Online (Sandbox Code Playgroud)

(仅供参考,如果它有助于理解我正在尝试做什么:我正在尝试确定是否有任何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 };
Run Code Online (Sandbox Code Playgroud)

哎呀,不编译!出于某种原因(我喜欢解释)我不能在equijoin中使用那个文字布尔值!好吧,我会把它留下来,然后过滤掉"RequiresPrescription"的东西......

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

...现在它编译 - 但是当我运行时,我在这一行上得到一个"对象引用未设置"异常. DUH! 当然那里有空!如果你不允许引用右侧的对象,那么你应该如何与左连接进行比较,这可能是空的?

那么,你应该如何使用多个字段进行左连接?

lc.*_*lc. 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 
};
Run Code Online (Sandbox Code Playgroud)

LinqUtils.GetTable<PayerServiceTypeRules>().DefaultIfEmpty()可能是因为返回DataTable不包含任何行而导致异常,从而导致异常.请注意,in在选择之后将执行整个语句,这不是您期望的行为.您希望匹配的行,如果不存在匹配的行,则返回null.


对于布尔问题,它是一个命名问题(没有匹配右侧的"RxReq",左侧没有匹配"RequiresPrescription").尝试命名上面的true"RequiresPrescription"(或命名右侧的pstr.RequiresPrescription"RxReq").

  • ...或者只是放弃,保存你的理智,并使用像Dapper.net这样的微型ORM (5认同)