我正在寻找解决这个问题的建议。我们有这个带有许多左外连接的大型SQL查询。
以下是查询:
Select Top 1 WA.BHATUS_ID, WA.[CRMBHG_WORKINGACCOUNT_ID], BA.BHATUS_ID, BA.[CRMBHG_BILLINGACCOUNT_ID], BAD.BHATUS_ID, [BAD].[CRMBHG_BILLINGADDRESS_ID], SAD.BHATUS_ID, [SAD].[CRMBHG_SERVICEADDRESS_ID], C.BHATUS_ID, [C].[CRMBHG_CONTACT_ID]
From BillingHiBHory As BH With (NoLock)
Left Outer Join WorkingAccount As WA With (NoLock)
On WA.UniversalAccountId = BH.UniversalAccountId
And WA.BillingRegion = BH.BillingRegion
Left Outer Join BillingAccount As BA With (NoLock)
On BA.UniversalAccountId = BH.UniversalAccountId
And BA.BillingRegion = BH.BillingRegion
Left Outer Join BillingAddress As BAD With (NoLock)
On BAD.Grouping = BH.Grouping
And BAD.SubGrouping = BH.SubGrouping
And BAD.BillingRegion = BH.BillingRegion
Left Outer Join dbo.SubScriberInfo SUB With (NoLock)
On SUB.Grouping = BH.Grouping
And SUB.SubGrouping = BH.SubGrouping
And SUB.BillingRegion = BH.BillingRegion
Left Outer Join ServiceAddress As SAD With (NoLock)
On SAD.ControlNumberAssigned = SUB.ServceControlNum
And SAD.BillingRegion = SUB.BillingRegion
Left Outer Join Contact As C With (NoLock)
On BH.AccountNum = C.AccountNum
And BH.BillingRegion = C.BillingRegion
Where BH.Grouping = @Grouping
And BH.SubGrouping = @SubGrouping
Order By BH.SequenceOrder, WA.StatusDate Desc, BA.StatusDate Desc, BAD.StatusDate Desc, SAD.StatusDate Desc, C.StatusDate Desc
这是我在LINQ语法中的第一次破解......
var statusIds = (
from wa in db.WorkingAccount
from ba in db.BillingAccount
from bad in db.BillingAddress
from si in db.SubscriberInfo
from sad in db.ServiceAddress
from c in db.CRMSTG_CONTACT
where wa.UniversalAccountId == UniversalSubscriberId && wa.BillingRegion == BillingRegion
where ba.UniversalAccountId == UniversalSubscriberId && ba.BillingRegion == BillingRegion
where bad.Grouping == Grouping && bad.SubGrouping == SubGrouping && bad.BillingRegion == BillingRegion
where si.Grouping == Grouping && si.SubGrouping == SubGrouping && si.BillingRegion == BillingRegion
where sad.ControlNumberAssigned == si.ServceControlNum && sad.BillingRegion == BillingRegion
where c.AccountNum == AccountNumber && c.BillingRegion == BillingRegion
orderby wa.StatusDate descending, ba.StatusDate descending, bad.StatusDate descending, sad.StatusDate descending, c.StatusDate descending
select new
{
workingAddressStatusId = wa.StatusId,
billingAccountStatusId = ba.StatusId,
billingAddressStatusId = bad.StatusId,
serviceAddressStatusId = sad.StatusId,
contactStatusId = c.StatusDate
}
).FirstOrDefault();
这主要起作用,但感觉就像一个大黑客。如果这个值下降,则其中一个StatusId值返回为null,而statusIds最终也为null。
我确信有更好的方法可以做到这一点。我愿意接受建议。
作为一个说明,是的,我知道TSQL上与“With(NoLock)”选项相关的风险,我们是一个非常繁忙的数据库上的辅助应用程序,我们不想创建阻塞链计费和支持人员开展工作。对于我们正在做的事情,NoLock不是问题。这不像我们正在使用聚合器进行多个查询联合。 ;)
答案 0 :(得分:1)
嗯,你有很多左外连接,并且LINQ中自然不支持左外连接,但是模式是众所周知的 - 看看左外加入join clause (C# Reference)中的和复合键部分,所以您只需遵循以下模式:
from bh in db.BillingHiBHory
join wa in db.WorkingAccount
on new { bh.UniversalAccountId, bh.BillingRegion }
equals new { wa.UniversalAccountId, wa.BillingRegion }
into bh_wa from wa in bh_wa.DefaultIfEmpty() // this turns the above (inner) join into left outer join
join ba in db.BillingAccount
on new { bh.UniversalAccountId, bh.BillingRegion }
equals new { ba.UniversalAccountId, ba.BillingRegion }
into bh_ba from ba in bh_ba.DefaultIfEmpty()
join bad in db.BillingAddress
on new { bh.Grouping, bh.SubGrouping, bh.BillingRegion }
equals new { bad.Grouping, bad.SubGrouping, bad.BillingRegion }
into bh_bad from bad in bh_bad.DefaultIfEmpty()
join si in db.SubscriberInfo
on new { bh.Grouping, bh.SubGrouping, bh.BillingRegion }
equals new { si.Grouping, si.SubGrouping, si.BillingRegion }
into bh_si from si in bh_si.DefaultIfEmpty()
join sad in db.ServiceAddress
on new { si.ServceControlNum, si.BillingRegion }
equals new { sad.ControlNumberAssigned, sad.BillingRegion }
into si_sad from sad in si_sad.DefaultIfEmpty()
join c in db.CRMSTG_CONTACT
on new { bh.AccountNum, bh.BillingRegion }
equals new { c.AccountNum, c.BillingRegion }
into bh_c from c in bh_c.DefaultIfEmpty()
where bh.Grouping == Grouping
&& bh.SubGrouping == SubGrouping
// ... (the rest)
要考虑的一个细节是在从左外连接的right
部分选择不可为空的字段时包含可空的强制转换。例如,如果StatusId
类型为int
,那么您需要使用以下内容:
select new
{
workingAddressStatusId = (int?)wa.StatusId,
// ...
}