Зачем использовать AsQueryable() вместо List()?

Я собираюсь использовать шаблон репозитория для доступа к данным с помощью Entity Framework и LINQ в качестве основы реализации не тестового репозитория. Большинство примеров, которые я вижу, возвращают AsQueryable(), когда вызов возвращает N записей вместо List. В чем преимущество этого?

4 ответа

Решение

AsQueryable просто создает запрос, инструкции, необходимые для получения списка. Позже вы можете внести дополнительные изменения в запрос, например, добавив новые предложения Where, которые будут отправлены полностью до уровня базы данных.

AsList возвращает фактический список со всеми элементами в памяти. Если вы добавите новую подсказку "Где", вы не сможете быстро фильтровать базу данных. Вместо этого вы получаете всю информацию в списке, а затем отфильтровываете то, что вам не нужно в приложении.

Так что в основном все сводится к ожиданию до последнего возможного момента, прежде чем совершить себя.

Возврате IQueryable<T> имеет преимущество в том, что выполнение является отложенным до тех пор, пока вы действительно не начнете перечислять результат, и вы сможете скомпоновать запрос с другими запросами и все же получить выполнение на стороне сервера.

Проблема в том, что вы не можете контролировать время жизни контекста базы данных в этом методе - вам нужен открытый контекст и вы должны убедиться, что он остается открытым до тех пор, пока не будет выполнен запрос. И тогда вы должны убедиться, что контекст будет ликвидирован. Если вы вернете результат как List<T>, T[]или что-то подобное, вы теряете отложенное выполнение и выполнение составленных запросов на стороне сервера, но вы получаете контроль над временем жизни контекста базы данных.

Что подходит лучше всего, конечно, зависит от реальных требований. Это другой вопрос без единой правды.

AsQueryable это метод расширения для IEnumerable<T> это может сделать две вещи:

  • Если IEnumerable<T> инвентарь IQueryable<T> просто бросает, ничего не делая.
  • В противном случае создает "подделку" IEnumerable<T> (EnumerableQuery<T>), который реализует каждый метод, компилирующий лямбды и вызывающий методы расширения Enumerable.

Так что в большинстве случаев использование AsQueryable бесполезно, если только вы не вынуждены передавать IQueryable методу, а вместо этого у вас есть IEnumerable, это взлом.

ПРИМЕЧАНИЕ: AsQueryable - это взлом, а IQueryable - нет!

Возврате IQueryable<T> будет откладывать выполнение запроса до тех пор, пока его результаты не будут фактически использованы. До этого вы также можете выполнять дополнительные операции запроса к базе данных на IQueryable<T>; на List Вы ограничены в целом менее эффективными операциями в памяти.

  • IQueryable: Это разновидность отложенного выполнения - отложенная загрузка, поэтому ваш запрос оценивается и попадает в базу данных. Если мы добавим какое-либо дополнительное предложение, оно попадет в базу данных с требуемым запросом с фильтрами.
  • IEnumerable: Выполняется загрузка, поэтому записи будут загружены сначала в памяти, а затем операция будет выполнена.

Итак, в зависимости от варианта использования, например, при подкачке огромного количества записей, мы должны использовать IQueryable<T>, если операция короткая и не создает большого использования памяти IEnumerable.

Другие вопросы по тегам