我是LINQ的新手,我正在努力寻找如何做到这一点。
我有一个具有sql server后端的系统,它使用EF5与数据库进行交互。我有以下表格
Case
CaseStatus
Status
CaseAction
ActionType
关系是......
Case (1 - many) CaseStatus
CaseStatus (1 - many) CaseAction
Status (1 - many) CaseStatus
ActionType (1 - many) CaseAction
我需要显示一个案例记录列表,其中包括最新状态(基于与案例相关的最后一个CaseStatus记录)和最新的Action记录(基于与最新CaseStatus记录相关的最新CaseAction记录)情况下)
所有案例至少都有CaseStatus记录,但并非所有CaseStatus记录都有相关的CaseAction记录。在这些场景中,我仍然需要显示Case记录中的一些细节,但我将Action列留空
在T-SQL中,这种东西会给我我想要的东西
select
c.ID CaseID
,cs1.Name CurrentStatus
,cs1.Date StatusDate
,ca1.Name LatestAction
,ca1.Date ActionDate
from
[Case] c
left join
--Latest CaseStatus record to get current status of case
(
select
cs.ID
,cs.CaseID
,s.Name
,cs.Date
,ROW_NUMBER() over (partition by caseid order by cs.id desc) rn
from
CaseStatus cs
--Join to status to get the name of the statusID
inner join Status s on cs.StatusID=s.ID
) cs1
on c.ID=cs1.CaseID and cs1.rn=1
left join
--Latest CaseAction on the case
(
select
ca.CaseStatusID
,at.Name
,ca.Date
,ROW_NUMBER() over (partition by casestatusID order by ca.id desc) rn
from
CaseAction ca
inner join ActionType at on ca.ActionTypeID=at.ID
) ca1
on ca1.CaseStatusID=cs1.ID and ca1.rn=1
我知道我可以做的一件事就是将我的数据放入我的应用程序中,在我的EF模型中包含包含此SQL的视图。
我想要的是,为了学习的目的,能够使用LINQ获得相同的结果。如果可能的话,我真的希望看到使用综合语法和扩展方法语法的例子
提前感谢您的任何帮助
答案 0 :(得分:1)
我假设你有一个Case
类,它具有Statuses
属性,它是CaseStatus
个对象的集合。此外,CaseStatus
对象具有Status
属性和一组名为Actions的CaseAction
对象。我还假设您有一个名为DbContext
的{{1}} - 后代实体,您可以通过该实体访问数据。
在这种情况下,查询相对简单:
context
答案 1 :(得分:0)
据我所知,linq中没有等效的ROW_NUMBER。
您需要在linq中使用几个groupjoin来实现相同的结果。 Groupjoin与DefaultIfEmpty相结合等同于SQL中的左连接(并在原始SQL中以相同方式发送)请参阅http://msdn.microsoft.com/en-us/library/vstudio/bb397895.aspx上的Microsoft示例
因此,在综合语法中,它将是:
var q = from c in db.Cases
join cs1 in
(
from cs in db.CaseStatus.OrderByDescending(x => x.ID)
join s in db.Status on cs.StatusId equals s.ID
join ca1 in
(
from ca in db.CaseAction.OrderByDescending(x => x.ID)
join a in db.Action on ca.ActionId equals a.ID
select new {ca, ActionName = a.Name}
)
on cs.ID equals ca1.ca.CaseStatusID
into caGrp
from caDft in caGrp.FirstOrDefault()
select new {cs,
StatusName = s.Name,
LastActionName = (caDft==null? String.Empty : caDft.ActionName)
LastActionDate = (caDft==null? String.Empty : caDft.ca.Date)
}
) on c.ID equals cs1.cs.CaseId
into csGrp
from csDft in csGrp.First()
select new {c, csDft};
return q.ToList().Select(x => new{
CaseID = x.c.ID,
StatusName = x.csDft.StatusName,
StatusDate = x.csDft.cs.Date,
ActionName = x.csDft.LastActionName,
ActionDate = x.csDft.LastActionDate
});
注意 - 它不是非常纯粹的综合linq,因为我使用了OrderByDescending扩展方法,但足够接近;)我将扩展方法版本留给其他人
答案 2 :(得分:0)
我设法提出以下似乎给了我所需要的东西。感谢指点家伙
var cases = db.Cases
.Select(c => new
{
CaseID = c.ID,
LatestStatus = c.CaseStatus
.Where(cs => cs.CaseID == c.ID)
.OrderByDescending(cs => cs.ID)
.FirstOrDefault()
})
.Select(c => new
{
CaseID = c.CaseID,
CurrentStatus = c.LatestStatus.Status.Name,
LatestAction = c.LatestStatus.CaseActions
.Where(ca => ca.CaseStatusID == c.LatestStatus.ID)
.OrderByDescending(ca => ca.ID)
.FirstOrDefault()
})
.Select(c => new CaseListItem
{
CaseID = c.CaseID,
CurrentStatus = c.CurrentStatus,
LastAction = c.LatestAction != null ? c.LatestAction.ActionType.Name : "-",
ActionDate = c.LatestAction != null ? c.LatestAction.Date : null
});