简体   繁体   English

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

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

I have a web application with two tables to track user shares. 我有一个带有两个表的Web应用程序来跟踪用户份额。 Shares must be approved and so they go through a series of status changes. 股份必须经过批准,才能进行一系列状态更改。 Each status change is recorded in the log and timestamped. 每个状态更改都记录在日志中并加盖时间戳。 The current status is always the last entry in the log for that particular share. 当前状态始终是该特定共享的日志中的最后一个条目。

Here are the entities (with brevity): 以下是实体(简洁):

Shares: ShareID UserName 共享:ShareID用户名

ShareLogs: LogID ShareID CreatedDate Status ShareLogs:LogID ShareID创建日期状态

I'm trying to get a list of Shares with their current status based on the last log entry. 我正在尝试根据上一个日志条目获取具有当前状态的共享列表。 Here is the SQL query that returns the correct result, but I'd like to do this using LINQ. 这是返回正确结果的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

I have written one LINQ query that seems to work, but I feel like there should be a better way, as this query looks pretty terrible. 我写了一个看起来不错的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;

You could try doing a join, then grouping on all rows except the ShareID, then just get the share with the greatest date. 您可以尝试进行联接,然后对除ShareID以外的所有行进行分组,然后仅获取日期最大的共享。 eg: 例如:

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});

That should do it! 那应该做! You can combine it into one statement if you'd like, I just separated them for clarity. 如果愿意,可以将其合并为一个语句,为了清楚起见,我将它们分开。

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);

Let me know if you see this as an improvement. 让我知道您是否认为这是一种改进。

Edit: I'm not 100% sure on where you need the Where filter so I left it. 编辑:我不是100%知道您需要在哪里过滤器,所以我离开了它。 I'm thinking it may be actually needed in the Let statement. 我认为Let语句中可能实际上需要它。 Or we could move it into the Comprehension syntax to be more consistent. 或者我们可以将其移至Comprehension语法中以使其更加一致。

I prefer method syntax, so here's my answer. 我更喜欢方法语法,所以这是我的答案。 Note I'm also doing a Group By but not a Join. 请注意,我也在进行分组依据,而不是联接。

 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 });

You should be able to group the ShareLogs to determine the correct ShareLog object (which contains the Code, Date and ShareID) - and then retrieve the Share by using the navigation property log.Share . 您应该能够对ShareLogs进行分组,以确定正确的ShareLog对象(其中包含Code,Date和ShareID),然后使用导航属性log.Share检索Share。

No need for a join, as far as I can see, because as it usually does LINQ has hidden that away via navigation properties. 据我所知,不需要联接,因为LINQ通常通过导航属性将其隐藏起来。

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

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