3

任何人都可以帮忙吗?

我有 1 个类,基本上它包含成员,并且在该类中是一个列表。

我在列表中的成员也是......所以基本上它是这样的,

我有 2 个成员,每个成员都有许多会话。

我希望只为每个成员返回 1 个会话。

我已经做了一个 LINQ 查询,但它当然不起作用......

我想我需要做一个自我加入,有什么想法吗?

基本上我的错误是我的子查询自加入中不存在 m 。

var sessions =  
from m in this.members                     
join s in
(
    from se in m.Sessions
    group se by se.Name into g
    select new {Name = g.Key, SessioEndTime = g.Max(a=>a.SessioEndTime)}
)   
on m.Name equals s.Name                    
select new { MemberName = m.Name, SessionTime = s.SessioEndTime}

我将不胜感激任何人的任何反馈。

提前致谢。

编辑

好的,我设法做到了以下几点,但这是最好的方法吗?

var sessions =  
from m in this.members                     
let sn = m.Sessions.OrderByDescending(a => a.SessionEndTime).FirstOrDefault()                
select new { MemberName = m.Name, SessionTime = sn.SessioEndTime}

这种方式 sn 包含1条记录,但我可以访问所有属性...

但这是使用 LET 的最佳方式吗?

谢谢。

4

1 回答 1

5

除非我错过了你需要的东西,不是吗?

var sessions = 
   from m in members
   select new { 
      MemberName = m.Name, 
      SessionTime = m.Sessions.Max(s => s.SessioEndTime)
   };

你必须改变你对 LINQ 查询的看法,更多地从对象的角度而不是从 SQL 实现的角度思考。我需要什么?我需要所有成员,每个成员都有其最新的会议结束时间,然后采取行动。

编辑: 您使用的 let 选项没问题,只要记住FirstOrDefault如果成员有一个空的 Session 列表将返回 null,然后 sn.SessionEndTime 命中 null 引用。另一方面,如果您确定每个成员至少有一个会话使用First或聚合。也不要FirstOrDefault()在 let 中使用,它会弄乱 LINQ 并阻止它与主服务器绑定(导致每个主服务器使用单独的 SQL 查询来检测丢失的子集),因此使用 let 的可用查询是:

from m in Members                     
let sn = m.Sessions.Max(s => s.SessioEndTime)                
select new { MemberName = m.Name, SessionTime = sn};

from m in Members                     
let sn = m.Sessions.OrderByDescending(a => a.SessioEndTime).First()              
select new { MemberName = m.Name, SessionTime = sn.SessioEndTime};

至于排序与最大聚合,两个查询都会生成一个子查询:

-- MAX    
SELECT [t0].[Name] AS [MemberName], (
    SELECT MAX([t1].[SessioEndTime])
    FROM [Session] AS [t1]
    WHERE [t1].[memberId] = [t0].[id]
    ) AS [SessionTime]
FROM [Member] AS [t0]
GO

-- ordering
SELECT [t0].[Name] AS [MemberName], (
    SELECT [t2].[SessioEndTime]
    FROM (
        SELECT TOP (1) [t1].[SessioEndTime]
        FROM [Session] AS [t1]
        WHERE [t1].[memberId] = [t0].[id]
        ORDER BY [t1].[SessioEndTime] DESC
        ) AS [t2]
    ) AS [SessionTime]
FROM [Member] AS [t0]

在 SessioEndTime 上使用降序索引时,排序脚本的速度大约慢了两倍(您可以获取这些执行计划以自行检查),而没有索引时,它的速度大约慢了 5 倍。

于 2011-02-17T10:23:45.007 回答