Я неправильно понимаю LINQ к SQL.AsEnumerable ()?

Рассмотрите этот код:

var query = db.Table
              .Where(t => SomeCondition(t))
              .AsEnumerable();

int recordCount = query.Count();
int totalSomeNumber = query.Sum();
decimal average = query.Average();

Принять query занимает очень долгое время для выполнения. Я должен получить количество записей, общее количество SomeNumberвозвращенный, и берут среднее число в конце. Я думал на основе своего чтения это .AsEnumerable() выполнил бы запрос с помощью LINQ-SQL, затем использовать LINQ к объектам для Count, Sum, и Average. Вместо этого когда я делаю это в LINQPad, я вижу, что тот же запрос выполняется три раза. Если я заменяю .AsEnumerable() с .ToList(), это только запрашивается однажды.

Я пропускаю что-то о какой AsEnumerable /?

48
задан Ocelot20 11 April 2015 в 01:40
поделиться

4 ответа

Вызов AsEnumerable () не выполняет запрос, а перечисление выполняет.

IQueryable - это интерфейс, который позволяет LINQ to SQL творить чудеса. IQueryable реализует IEnumerable , поэтому, когда вы вызываете AsEnumerable () , вы меняете методы расширения, вызываемые оттуда, то есть из IQueryable -методы к IEnumerable -методы (то есть переход с LINQ to SQL на LINQ to Objects в данном конкретном случае). Но вы не выполняете фактический запрос, а просто меняете то, как он будет выполняться полностью.

Чтобы принудительно выполнить запрос, необходимо вызвать ToList () .

60
ответ дан 26 November 2019 в 18:50
поделиться

Я предполагаю, что ToList заставляет Linq получить записи из базы данных. Когда вы затем выполняете дальнейшие вычисления, они производятся с объектами в памяти, а не с базой данных.

Если оставить тип возврата как Enumerable, это означает, что данные не извлекаются до тех пор, пока к ним не обратится код, выполняющий вычисления. Я полагаю, что это приводит к тому, что к базе данных обращаются три раза - по одному для каждого вычисления, и данные не сохраняются в памяти.

1
ответ дан 26 November 2019 в 18:50
поделиться

Да. Все, что сделает AsEnumerable , - это вызовет выполнение функций Count , Sum и Average на стороне клиента (другими словами, он вернет клиенту весь набор результатов, затем клиент будет выполнять эти агрегаты вместо создания операторов COUNT () SUM () и AVG () в SQL. ).

14
ответ дан 26 November 2019 в 18:50
поделиться

Что ж, вы на правильном пути. Проблема в том, что IQueryable (то, что было перед вызовом AsEnumerable ) также является IEnumerable , так что этот вызов, по сути, является nop. Для принудительного выполнения запроса потребуется принудительно использовать определенную структуру данных в памяти (например, ToList () ).

4
ответ дан 26 November 2019 в 18:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: