Если я не пропустил что-то, что вам нужно, нет?
var sessions =
from m in members
select new {
MemberName = m.Name,
SessionTime = m.Sessions.Max(s => s.SessioEndTime)
};
Вы должны изменить свой подход к LINQ-запросам, больше думать с точки зрения объекта, а не с точки зрения реализации SQL. Что мне нужно? Мне нужно, чтобы все участники, каждый со своим последним временем окончания сеанса, затем приступили к этому.
EDIT:
С опцией let, которую вы использовали, все в порядке, просто имейте в виду, что FirstOrDefault
вернет ноль, если у члена пустой список сессий, а затем sn.SessionEndTime попадет на нулевую ссылку. Если, с другой стороны, вы уверены, что у каждого участника есть хотя бы один сеанс, используйте 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, оба запроса будут генерировать подзапрос:
-- 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 раз медленнее.