2009-07-07 62 views
12

我刚才问了一个关于why left joins in Linq can't use defined relationships的问题;迄今为止我还没有得到满意的答复。如果连接中有多个字段,你如何在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 

(仅供参考,如果它有助于理解我想要做的事:我想,以确定是否有任何。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!当然,那里是空的!如果您不允许在右侧引用该对象,那么您还应该如何执行与左连接的比较,那可能是空的?

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

+1

对于布尔问题,它不能是一个命名问题(右侧没有任何匹配的“RxReq”,没有匹配左侧的“RequiresPrescription”)?尝试命名布尔型“RequiresPrescription”或专门命名右侧的pstr.RequiresPrescription“RxReq”。 – 2009-07-07 16:58:11

回答

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”命名)。

+3

...或者放弃,保存您的理智,并使用像Dapper.net这样的微型ORM – niico 2016-05-09 20:07:19