繁体   English   中英

C#LINQ与实体一对多关系:显示最后的日志条目数据时出现问题

[英]C# LINQ to Entities One-To-Many relationship: Problem displaying last log entry data

我有一个带有两个表的Web应用程序来跟踪用户份额。 股份必须经过批准,才能进行一系列状态更改。 每个状态更改都记录在日志中并加盖时间戳。 当前状态始终是该特定共享的日志中的最后一个条目。

以下是实体(简洁):

共享:ShareID用户名

ShareLogs:LogID ShareID创建日期状态

我正在尝试根据上一个日志条目获取具有当前状态的共享列表。 这是返回正确结果的SQL查询,但我想使用LINQ进行此操作。

SELECT s.ShareID, s.UserName, sl.Code, sl.CreatedDate
FROM Shares s
INNER JOIN 
(
SELECT s.ShareID, s.Code, s.CreatedDate
    FROM ShareLogs sl
    INNER JOIN (SELECT ShareID, MAX(CreatedDate) logDate FROM ShareLogs GROUP BY ShareID) sl2
        ON sl.ShareID = sl2.ShareID AND sl.CreatedDate = sl2.logDate) psl1
ON s.ShareID = sl1.ShareID
ORDER BY s.ShareID

我写了一个看起来不错的LINQ查询,但是我觉得应该有更好的方法,因为这个查询看起来很糟糕。

var query = from list in
(from s in context.Shares
join sl in context.ShareLogs on s.ShareID equals sl.ShareID
where sl.CreatedDate == s.ShareLogs.Max(e => e.CreatedDate)
select new
{
 share = s
 status = sl.Code,
 processDate = sl.CreatedDate
}).Where(e => e.status == 2 || e.status == 3)
select list;

您可以尝试进行联接,然后对除ShareID以外的所有行进行分组,然后仅获取日期最大的共享。 例如:

var shareList = context.Shares;
var shareLogList = context.ShareLogs;
var join = shareList.Join(shareLogList, o=>o.ShareID, i=>i.ShareID, s=>new{o.ShareID, o.UserName,i.LogID, i.CreatedDate, i.Status});
var query = join.GroupBy(g=>new{g.ShareID,g.UserName}, (key,lines)=>new{key.ShareID, Status = lines.Max(m=>m.CreatedDate).Status});

那应该做! 如果愿意,可以将其合并为一个语句,为了清楚起见,我将它们分开。

var query = (from s in context.Shares
            let latestOrder = s.ShareLogs                                             
                                         .OrderByDescending(sl => sl.CreatedDate)
                                         .First()
            select new 
            {
                share = s,
                status = latestOrder.Code,
                processDate = latestOrder.CreatedDate
            }).Where(sl => sl.status == 2 || sl.status ==3);

让我知道您是否认为这是一种改进。

编辑:我不是100%知道您需要在哪里过滤器,所以我离开了它。 我认为Let语句中可能实际上需要它。 或者我们可以将其移至Comprehension语法中以使其更加一致。

我更喜欢方法语法,所以这是我的答案。 请注意,我也在进行分组依据,而不是联接。

 context.ShareLogs.GroupBy(log => log.ShareID)
     .Select(g => g.Logs.Single(log => 
         log.CreatedDate == g.Logs.Max(g => g.CreatedDate)))         
     .Select(l => new { Share = l.Share, Status = l.Code, Date = l.CreatedDate });

您应该能够对ShareLogs进行分组,以确定正确的ShareLog对象(其中包含Code,Date和ShareID),然后使用导航属性log.Share检索Share。

据我所知,不需要联接,因为LINQ通常通过导航属性将其隐藏起来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM