Я заметил несколько проблем в ответе @ gunny229 выше, поэтому я пишу этот пост. Я также упомянул эти проблемы в комментариях к его сообщению. Чтобы исправить этот пост, мне пришлось бы переписать почти весь пост, поэтому я подумал о создании своего собственного. Я не собираюсь полностью отвечать на вопрос OP, но хочу указать на разницу между IQueryable и IEnumerable при использовании LINQ to SQL.
Я создал в БД следующую структуру (DDL-скрипт):
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
Вот сценарий вставки записи (сценарий DML):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
Теперь моей целью было просто получить две первые записи из Employee
таблицы в базе данных. Итак, я добавил элемент модели данных сущности ADO.NET в свое консольное приложение, указывающий на Employee
таблицу в моей базе данных, и начал писать запросы LINQ.
Код для маршрута IQueryable:
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Когда я начал запускать эту программу, я также запустил сеанс профилировщика SQL Query на моем экземпляре SQL Server, и вот сводка выполнения:
- Общее количество запущенных запросов: 1
- Текст запроса:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
Просто IQueryable
достаточно умен, чтобы применить предложение Top (2)
на самой стороне сервера базы данных, поэтому он передает только 2 из 5 записей по сети. Дальнейшая фильтрация в памяти на стороне клиентского компьютера вообще не требуется.
Код для IEnumerable маршрута:
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Краткое содержание исполнения в этом случае:
- Общее количество запущенных запросов: 1
- Текст запроса, записанный в профилировщике SQL:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
Теперь дело в том, что IEnumerable
принесла все 5 записей, присутствующих в Salary
таблице, а затем выполнила фильтрацию в памяти на клиентском компьютере, чтобы получить 2 первые записи. Таким образом, больше данных (в данном случае 3 дополнительных записи) было без надобности передано по сети.
person
RBT
schedule
26.04.2017