Куда загружаются данные? - PullRequest
0 голосов
/ 02 ноября 2018

Я заметил, что многие люди не понимают, как выполняются запросы для извлечения данных из базы данных.

Часто встречается код, подобный следующему:

var reader = await sqlCommand.ExecuteReaderAsync();
dataTable.Load(reader);

Существует несколько ответов о StackOverflow, которые представляют его как асинхронную загрузку данных в DataTable.

Однако я считаю, что метод ExecuteReader не загружает данные, а только создает экземпляр считывателя.

Я могу подтвердить это цитатой из официальной документации :

DataReader предоставляет небуферизованный поток данных, который позволяет процедурная логика для эффективной обработки результатов из источника данных последовательно. DataReader - хороший выбор при извлечении большие объемы данных, поскольку данные не кэшируются в памяти.

Один человек в споре со мной процитировал ссылку и заявил, что там происходит загрузка данных. Но я не вижу вызова метода Read внутри этого кода! Между тем, метод ExecuteScalarAsync чуть ниже имеет такой вызов.

Следовательно, данные будут загружены с помощью метода DataTable.Load или с помощью цикла while(reader.Read()). Я прав?

Итак, куда загружаются данные: в методе ExecuteReader(Async) или в методе Read/Load?

1 Ответ

0 голосов
/ 02 ноября 2018

Когда данные на самом деле получены, это немного сложный вопрос, потому что вы используете DataReader.

По своей сути DataReader работает как Перечислители . Read () делает вещи, сравнимые с Current (Current является свойством, поэтому это вызов функции, не похожий на единицу). В обоих случаях я не могу сказать вам, когда именно Данные передаются / полностью встроены в память. Это деталь реализации. Я могу сказать вам, что он был полностью извлечен, когда Read / Current возвращает значение «Я закончил», а не следующий результат.

Если я создаю Enumerator из массива, то все данные уже находятся в памяти. И этот случай не редкость, это происходит каждый раз, когда вы вызываете цикл foreach! Foreach не работает с коллекциями, только с перечислителями. К счастью, получение перечислителя из коллекции настолько тривиально, что это неявное преобразование.

С другой стороны, перечислитель может быть построен из внешнего источника данных. Например, Directory.EnumerateFiles () или File.ReadLines () . Последнее, следующая строка загружается точно при вызове Current. Однако, если разработчик кода несколько умен, то следующие 1-многие результаты будут загружены в фоновом режиме между текущими вызовами. И сколько он загружает вперед, может даже зависеть от среды (сколько оперативной памяти вы должны тратить на это). Если при вызове Current данные уже есть, они возвращаются. Если нет, Current становится блокирующим вызовом до тех пор, пока не будет получен следующий результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...