LINQ имеет много воплощений. Поскольку вы упоминаете LINQ-to-SQL, я сосредоточусь на этом: он ни то, ни другое ... он наиболее сопоставим с IDataReader
- то есть он выполняет построенную команду TSQL, а затем возвращает обработанные записи построчно (см. ниже), как он получает их от SQL Server. Как и в случае IDataReader
, вы получаете только один шанс на строку, если только вы не буферизируете данные, используя .ToArray()
, .ToList()
и т. Д.
Выполненная команда TSQL построена на основе созданного вами запроса LINQ и параметризована для предотвращения внедрения SQL - поэтому если вы используете «где», выполняемый TSQL включает «WHERE» и т. Д.
В действительности, клиент потребляет записи по требованию через IEnumerable[<T>]
, поэтому для обработки входящего потока TDS должен быть небольшой буфер, но он не совпадает с курсором базы данных.
Обратите внимание, что большинство операций (сортировка и т. Д.) Могут быть отправлены на сервер и переведены на TSQL - но возможно, что некоторые действия необходимо выполнить на клиенте, что может снова заставить его буферизовать больше данных в памяти , Это особенно верно, если вы заставите его через .ToEnumerable()
, который переключается на LINQ-to-Objects. Если LINQ-to-Objects выполняет операцию буферизации (сортировку, группировку и т. Д.), То ему потребуется загрузить данные в память.
Здесь следует отметить несколько вещей; например, если вы хотите вычислить полностью отдельные агрегаты и т. д. в запросе, вы должны (обычно) выполнить его дважды (и т. д.) или поместить его в буфер (не обязательно для больших данных). Для этого типа сценария (и других) Джон Скит и я написали альтернативную реализацию LINQ, которая работает как push , а не pull , позволяя передавать данные через несколько параллельных процессов. однажды. Джон объясняет это лучше здесь . Этот тип вещей в основном используется, если у вас есть очень большой, однократный поток данных, для которого вы хотите выполнить сложную обработку. Интересно, хотя.