Язык программирования C#9 и платформа .NET5
Объекты чтения данных удобны, если нужно быстро пройти по большому объему данных без необходимости иметь их представление в памяти. Например, в случае запрашивания 20 000 записей из таблицы с целью их сохранения в текстовом файле помещение такой информации в объект
приведет к значительному расходу памяти (посколькуDataSetхранит полный результат запроса в памяти).DataSetБолее эффективный подход предусматривает создание объекта чтения данных, который максимально быстро проходит по всем записям. Тем не менее, имейте в виду, что объекты чтения данных (в отличие от объектов адаптеров данных, которые рассматриваются позже) удерживают подключение к источнику данных открытым до тех пор, пока вы его явно не закроете.
Объекты чтения данных получаются из объекта команды с применением вызова
. Объект чтения данных представляет текущую запись, прочитанную из базы данных. Он имеет метод индексатора (например, синтаксисExecuteReader()в языке С#), который позволяет обращаться к столбцам текущей записи. Доступ к конкретному столбцу возможен либо по имени, либо по целочисленному индексу, начинающемуся с нуля.[]В приведенном ниже примере использования объекта чтения данных задействован метод
, с помощью которого выясняется, когда достигнут конец записей (в случае чего он возвращаетRead()). Для каждой прочитанной из базы данных записи с применением индексатора типа выводится модель, дружественное имя и цвет каждого автомобиля. Обратите внимание, что сразу после завершения обработки записей вызывается методfalse, которые освобождает объект подключения.Close()...// Получить объект чтения данных посредством ExecuteReader().using(SqlDataReader myDataReader = myCommand.ExecuteReader()){// Пройти в цикле по результатам.while (myDataReader.Read()){WriteLine($"-> Make: { myDataReader["Make"]},PetName: { myDataReader["PetName"]},Color: { myDataReader["Color"]}.");}}ReadLine();Индексатор объекта чтения данных перегружен для приема либо значения
(имя столбца), либо значенияstring(порядковый номер столбца). Таким образом, текущую логику объекта чтения можно сделать яснее (и избежать жестко закодированных строковых имен), внеся следующие изменения (обратите внимание на использование свойстваint):FieldCountwhile (myDataReader.Read()){for (int i = 0; i < myDataReader.FieldCount; i++){Console.Write(i != myDataReader.FieldCount - 1? $"{myDataReader.GetName(i)} = {myDataReader.GetValue(i)}, ": $"{myDataReader.GetName(i)} = {myDataReader.GetValue(i)} ");}Console.WriteLine();}Если в настоящий момент скомпилировать проект и запустить его на выполнение, то должен отобразиться список всех автомобилей из таблицы Inventory базы данных
. В следующем выводе показано несколько начальных записей:AutoLot***** Fun with Data Readers ********** Info about your connection *****Database location: .,5433Database name: AutoLotTimeout: 30Connection state: Openid = 1, Make = VW, Color = Black, Petname = Zippyid = 2, Make = Ford, Color = Rust, Petname = Rustyid = 3, Make = Saab, Color = Black, Petname = Melid = 4, Make = Yugo, Color = Yellow, Petname = Clunkerid = 5, Make = BMW, Color = Black, Petname = Bimmerid = 6, Make = BMW, Color = Green, Petname = Hankid = 7, Make = BMW, Color = Pink, Petname = Pinkyid = 8, Make = Pinto, Color = Black, Petname = Peteid = 9, Make = Yugo, Color = Brown, Petname = BrownieПолучение множества результирующих наборов с использованием объекта чтения данных
Объекты чтения данных могут получать несколько результирующих наборов с применением одиночного объекта команды. Например, если вы хотите получить все строки из таблицы
, а также все строки из таблицыInventory, тогда можете указать два SQL-оператораCustomers, разделив их точкой с запятой:Selectsql += ";Select * from Customers;";На заметку! Точка с запятой в начале строки опечаткой не является. В случае использования множества операторов они должны разделяться точками с запятой. И поскольку начальный оператор не содержал точку с запятой, она добавлена здесь в начало второго оператора.
После получения объекта чтения данных можно выполнить проход по каждому результирующему набору, используя метод
. Обратите внимание, что автоматически возвращается первый результирующий набор. Таким образом, если нужно прочитать все строки каждой таблицы, тогда можно построить следующую конструкцию итерации:NextResult()do{while (myDataReader.Read()){for (int i = 0; i < myDataReader.FieldCount; i++){Console.Write(i != myDataReader.FieldCount - 1? $"{myDataReader.GetName(i)} = {myDataReader.GetValue(i)}, "