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

C#LINQ到实体的一对多关系:显示上次日志条目数据时出现问题,c#,linq,frameworks,entity,one-to-many,C#,Linq,Frameworks,Entity,One To Many,我有一个web应用程序,它有两个表来跟踪用户共享。股票必须经过批准,因此要经历一系列的状态变化。每个状态更改都记录在日志中并加上时间戳。当前状态始终是该特定共享的日志中的最后一项 以下是实体(简短): 股份: 共享ID 用户名 共享日志: 罗吉德 共享ID 创建数据 地位 我正在尝试根据上一个日志条目获取当前状态的共享列表。 下面是返回正确结果的SQL查询,但我想使用LINQ来实现这一点 SELECT s.ShareID, s.UserName, sl.Code, sl.CreatedDate

我有一个web应用程序,它有两个表来跟踪用户共享。股票必须经过批准,因此要经历一系列的状态变化。每个状态更改都记录在日志中并加上时间戳。当前状态始终是该特定共享的日志中的最后一项

以下是实体(简短):

股份: 共享ID 用户名

共享日志: 罗吉德 共享ID 创建数据 地位

我正在尝试根据上一个日志条目获取当前状态的共享列表。 下面是返回正确结果的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%确定在哪里需要where过滤器,所以我留下了它。我想在Let声明中可能真的需要它。或者我们可以把它移到理解语法中,以便更加一致。

我更喜欢方法语法,下面是我的答案。注意,我也在做分组,但不是加入

 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对象(其中包含代码、日期和ShareID),然后使用导航属性
log.Share
检索共享


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

共享
共享日志
之间的关系在
对象上下文
中定义的,因此
EntitySet
共享
的成员吗,我已经在上下文中清楚地定义了所有必要的关系信息。