Почему в классе LINQ to SQL свойства создаются из объектов внешних ключей EntitySet, которые реализуют IEnumerable, тогда как в качестве объектов на DataContext используются объекты Table, которые реализуют IQueryable?
Обновлено: Чтобы прояснить, вот пример, который иллюстрирует то, что я пытаюсь понять. Этот пример:
ctx.Matches.Where(x => x.MatchID == 1).Single()
.MatchPlayers.Max(x => x.Score);
дважды попадает в базу данных, где:
ctx.MatchPlayers.Where(x => x.MatchID == 1)
.Max(x => x.Score);
выполняется только 1 запрос. Вот следы:
exec sp_executesql N'SELECT [t0].[MatchID], [t0].[Date]
FROM [dbo].[Matches] AS [t0]
WHERE [t0].[MatchID] = @p0',N'@p0 int',@p0=1
go
exec sp_executesql N'SELECT [t0].[MatchID], [t0].[PlayerID], [t0].[Score]
FROM [dbo].[MatchPlayers] AS [t0]
WHERE [t0].[MatchID] = @p0',N'@p0 int',@p0=1
go
и
exec sp_executesql N'SELECT MAX([t0].[Score]) AS [value]
FROM [dbo].[MatchPlayers] AS [t0]
WHERE [t0].[MatchID] = @p0',N'@p0 int',@p0=1
go
что также показывает, что, что еще хуже, максимум выполняется на уровне C#, а не в базе данных.
Я знаю, что причина, по которой это происходит, заключается в различии между IQueryable и IEnumerable, так почему же объект MatchPlayers в первом примере не реализует интерфейс IQueryable, чтобы получить те же преимущества, что и во втором примере.





Таблицы, по сути, концептуальный вопрос - они действительно существуют на сервере, поэтому вам нужно запрашивать, чтобы получить записи. Записи внешнего ключа - это те записи, которые фактически извлекаются другим запросом, поэтому в этот момент они доступны локально. Это довольно туманное описание, но, надеюсь, оно выходит за рамки общей концепции.
ctx.Matches.Where(x => x.MatchID == 1).Single()
Single () возвращает Match, а не IQueryable (Match).
Просто переместите Single () на последний шаг:
ctx.Matches
.Where(m => m.MatchID == 1)
.Select(m => m.MatchPlayers.Max(mp => mp.Score))
.Single();
Этот запрос показывает, что можно использовать свойство MatchPlayers в запросе. Что касается моей интерпретации вопроса спрашивающего - «Почему я не могу использовать EntitySet в запросе?», Вы можете.
Это был рассматривается на форумах MSDN. Суть аргументации заключается в том, что очень сложно отслеживать добавленные и удаленные объекты при выполнении запросов к базе данных. Вместо этого EntitySet - это что-то вроде локальной копии связанных объектов, которыми вы можете манипулировать. К сожалению, как вы заметили, это имеет побочный эффект передачи выражений в вызовы LINQ to Objects вместо более производительного LINQ to SQL.