【问题标题】:How do you left join in Linq if there is more than one field in the join?如果联接中有多个字段,您如何在 Linq 中离开联接?
【发布时间】:2009-07-07 16:53:31
【问题描述】:

我之前问过一个关于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

(仅供参考,如果有助于理解我正在尝试做的事情:我正在尝试确定此 Patient 是否有任何 TreatmentPlanDetail 记录,其中授权 Payer 需要对此 @ 的处方987654327@,但要么没有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 };

糟糕,无法编译!出于某种原因(我想解释一下)我不能在等值连接中使用那个字面布尔值!好吧,我先不说,稍后过滤掉“RequiresPrescription”的东西……

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

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

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

【问题讨论】:

  • 对于布尔问题,难道不是命名问题(右侧没有匹配“RxReq”,左侧没有匹配“RequiresPrescription”)?尝试将布尔值命名为“RequiresPrescription”或将右侧的 pstr.RequiresPrescription 命名为“RxReq”。

标签: c# linq linq-to-sql join left-join


【解决方案1】:

我认为您需要使用 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&lt;PayerServiceTypeRules&gt;().DefaultIfEmpty() 可能会出现空值,因为返回的 DataTable 不包含任何行,从而导致您的异常。请注意,in 之后的整个语句将在选择之前执行,这不是您想要的行为。如果不存在匹配的行,则需要匹配的行或 null。


对于布尔问题,这是一个命名问题(右侧没有匹配“RxReq”,左侧没有匹配“RequiresPrescription”)。尝试像上面那样命名true“RequiresPrescription”(或命名右侧的pstr.RequiresPrescription“RxReq”)。

【讨论】:

  • ...或者干脆放弃,保持理智,使用像 Dapper.net 这样的微型 ORM
猜你喜欢
  • 1970-01-01
  • 2017-01-26
  • 1970-01-01
  • 2011-05-07
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多