1

我是 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 记录)和最新的操作记录(基于与与案例相关的最新 CaseStatus 记录相关的最新 CaseAction 记录)

所有案例都至少有 CaseStatus 记录,但并非所有 CaseStatus 记录都有相关的 CaseAction 记录。在这些情况下,我仍然需要显示案例记录中的一些详细信息,但我会将操作列留空

在 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 获得相同的结果。如果可能的话,我真的很想看看使用综合语法和扩展方法语法的例子

提前感谢您的任何帮助

4

3 回答 3

1

我假设您有一个具有属性的Case类,该Statuses属性是CaseStatus对象的集合。此外,该CaseStatus对象具有一个Status属性和一个CaseAction称为 Actions 的对象集合。我还将假设您有一个DbContext调用的 -descendant 实体context,您可以通过该实体访问数据。

在这种情况下,查询相对简单:

context.Cases.Select( c=> {
   //get the last status
   var lastStatus = c.Statuses.OrderByDescending(cs => cs.ID).First();
   //get the last action (might be null)
   var lastAction = lastStatus.OrderByDescending(ca => ca.ID).FirstOrDefault();
   return new 
   {
      CaseID = c.ID,
      StatusName = lastStatus.Status.Name,
      StatusDate = lastStatus.Date,
      ActionName = (lastAction == null) ? null : lastAction.Action.Name,
      ActionDate = (lastAction == null) ? null : lastAction.Date,
   }
});
于 2013-09-02T13:45:53.637 回答
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 扩展方法,但足够接近;)我会将扩展方法版本留给其他人

于 2013-09-02T14:12:02.667 回答
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
                        });
于 2013-09-03T15:55:45.590 回答