Работа с автономными данными в ADO.NET
Кондратьев Денис
Технология ADO.NET, в отличие от своих предшественников ADO и OLE DB, была разработана специально для использования в web приложениях, где не бывает постоянных соединений с БД. Традиционная работа с данными в ADO.NET строится по такой схеме: создается соединение Connection, затем оно открывается методом Open, создается объект команда Command, инкапсулирующая SQL команду, она исполняется, а соединение затем закрывается. Такой подход обеспечивает поточный доступ к результатам запросов. Т.е. читая данные с помощью DataReader, вы не можете перепрыгнуть через несколько записей или вернуться к предыдущей. Поточный доступ имеет максимальную производительность. ADO.NET была разработана для доступа к данным без реального соединения с БД. При этом все данные размещаются в оперативной памяти. Работа с отсоединенными данными в ADO.NET осуществляется с помощью классов из пространства имен System.Data. Самый выжный класс при работе с отсоединенными данными - это DataSet. После того как получены результаты запроса с помощью объекта DataAdapter и сохранены в DataSet' e, соединение между БД и объектом DataSet перестает существовать. Изменения в DataSet не сказываются на БД и наоборот. Класс DataSet включает в себя набор таблиц DataTable и связей между таблицами DataRelation. Класс DataTable включает набор строк DataRow, набор столбцов таблицы DataColumn, и наборы отношений ChildRelations и ParentRelations между столбцами разных таблиц базы данных. Класс DataRow инкапсулирует информацию о строке в таблице и состоянии строки Deleted, Modified, New и Unchanged. Класс Constraint используется для сохранения целостности данных в таблицах. Использование объектов DataSetНиже приводится пример использования объекта DataSet. Все примеры в статье используют БД Northwind БД MS SQL Server. stringconn ="Provider=SQLSQL;Data Source=(local)\\NetSDK;InitialCatalog=Northwind;Trusted_Connection=Yes;"; Вначале создаем строку соединения с БД и SQL запрос для получения данных. DataAdapter помещает результаты запроса в соответствующую таблицу DataTable, находящуюся в DataSet. С помощью перегруженного метода Fill можно помещать данные и напрямую в DataTable. Для одной таблицы можно несколько раз вызывать метод Fill, однако, если вызывать метод Fill для DataSet без явного указания имени таблицы, то эти данные будут помещаться в разные таблицы (например, "Table", "Table1", "Table2",). Для доступа к данным, находящимся в таблицу есть свойство Rows, возвращающее набор объектов DataRow DataTable table = ds.Tables[0]; У объекта DataRow есть свойство Item, возвращающее содержимое конкретного поля. Можно указать имя поля как в примере кода, или целое число, соответствующее порядковому номеру столбца. При поиске по индексу данные немного возвращаются быстрее, чем при поиске по названию столбца. Изменение содержимого DataTableДля добавления новой строки в таблицу существует метод NewRow(), который создает новый объект DataRow, но не добавляет запись в таблицу. Полем новой записи задаются значения по умолчанию или Null, если значение по умолчанию не задано. DataRow row = ds.Tables["Customers"].NewRow(); Есть еще один способ добавления записей в таблицу - метод LoadDataRow(). Первый параметр этого метода - это массив значений, элементы которого соответствуют столбцам таблицы. Второй - позволяет управлять значением свойство RowState новой записи. Если передать false, то значение этого свойства будет Added, как и при добавлении новой записи методом Add. object[]aValues = {"VASYA", "Компания", "Вася Пупкин", "11-22-33"}; Редактирование существующей записи можно следующим образом: DataRow row = ds.Tables["Customers"][0]; или с помощью метода ItemArray: object[] items = {"VASYA", "Компания", "Вася Пупкин", "11-22-33"}; Для удаления записи нужно вызывать метод DataRow.Delete(). При этом удаленная запись фактически не удаляется из DataTable, а помечается как удаленная - ее свойство RowState принимает значение Deleted. Если же до вызова метода Delete значение RowState было Added, тотолько в этом случае строка удаляется из таблицы. Использование столбцов с автоинкрементном Для поддержки столбцов с автоматическим увеличением значения у DataColumn есть свойства AutoIncrement, AutoIncrementSeed и AutoIncrementStep . Для того, чтобы создать столбец DataColumn с автоинкрементом нужно установить свойство AutoIncrement в true. Значение счетчика будет начинаться с AutoIncrementSeed (если это не нарушает корректность данных в таблице) и увеличиваться на значение AutoIncrementStep. Для столбцов с автоинкрементном рекомендуется устанавливать свойство ReadOnly в true. Ниже приведен пример вставки в таблицу столбца с автоинкрементом DataColumn column = table.Columns.Add("CustomerID", typeof(Int32)); Если вы планируете сносить изменения в БД методом DataAdapter.Update(), то рекомендуется задать свойствам AutoIncrementSeed и AutoIncrementStep значения -1. Это гарантирует, что ADO.NET будет генерировать значения метки, которых нет в БД. При вызове метода Update в БД внесутся уже уникальные значения. Работа с DataSet в среде Visual Studio .NETСоздавать объекты DataSet можно как программно, так и с помощью среды Visual Studio. Для второго случая предназначена вкладка Data в панели инструментов. Для начала нужно перетащить на web или win-форму объект SqlDataAdapter. Затем в мастере создать новое подключение к БД, указав БД Northwind и способ доступа к БД как . После этого выберете таблицу Customers и отметьте все столбцы таблицы. Повторите процесс для таблицы Order, используя уже готовое соединение. Затем щелкните правой кнопкой мыши по панели с созданными DataAdapter 'ами, выберете из контекстного меню команду Generate DataSet. Отметьте галочками оба DataAdapter и нажмите на ОК. Добавленный объект DataSet отобразился в панели компонентов. Мы добавили т.н. DataSet со строгим контролем типов (типизированный DataSet ), о котором будем говорить позже. Структуру данных можно посмотреть в созданном файле с расширением xsd. Другой путь создания типизированных датасетов - добавление в проект DataSet (через команду Add New Item) и "перетаскивание" на него таблиц БД из окна Server Explorer. Работа с реляционными даннымиРабота с реляционными данными осуществляется с помощью объектов класса DataRelation, связующие колонки DataColumn двух таблиц DataTable. Создать такой объект можно следующим образом: ds.Relationships.Add(new DataRelation("CustomersOrders", ds.Tables["Customers"].Columns["CustomerID"], ds.Tables["Orders"].Columns["CustomerID"]); Если нужно определить отношение, основанное на нескольких столбцах, нужно использовать конструктор, принимающий массив объектов DataColumn: DataTable tblParent = ds.Tables["ParentTable"]; Работа со связанными данными Основным применением объектов DataRelation является поиск связанных данных. Однако сам объект DataRelation не предоставляет такой функциональности, она реализуется методами класса DataRow: GetChildRow(), GetParentRow() и GetParentRows(). DataRow row = ds.Tables["Customers"].Rows[0]; Найти родительскую запись с помощью DataRelation можно методом DataRow.GetParentRow (). DataRow rowOrder = ds.Tables["Orders"].Rows[0]; В случае отношения <один ко многим> найти все родительские записи конкретного объекта DataRow можно с методом GetParentRows(), также принимающего название отношения и возвращающего массив родительских объектов. Добавление объекта DataRelation в Visual Studio .NETДля добавления отношения DataRelation в DataSet со строгим контролем типов нужно перейти к структуре данных, щелкнув по файлу с расширением xsd, определяющего структуру DataSet. Щелкнув на родительский DataTable правой кнопкой нужно в контекстном меню выбрать Add / New Relation. В диалоговом окне Edit Relation задаются родительские и дочерние объекты. При щелчке на ОК, в XML Sheme Designer появляется графическое представление DataRelation - линия, соединяющая 2 объекта. Поиск записейПри запросах к БД часто требуется найти запись по ее первичному ключу. Для поиска записей в DataTable существует метод DataRowCollection.Find (). table.PrimaryKey = new DataColumn[] {tbl.Columns["CustomerID"]}; Если первичный ключ состоит из нескольких колонок, то в метод Find() можно передать массив объектов. DataRow[] rows = table.Select("City = 'Уфа'"); Если нужно, чтобы возвращаемые данные были отсортированы, можно воспользоваться перегруженной версией этого метода. Она имитирует раздел ORDER BY SQL -запроса. DataRow[] rows = table.Select("City = 'Уфа'", "CompanyName ASC"); Работа с объектами DataSet со строгим контролем типовРанее мы уже создавали объекты DataSet со строгим контролем типов. Рассмотрим, какие новые функции появились у типизированного DataSet. Добавление записиВсе классы, соответствующие таблицам DataTable в DataSet, позволяют добавлять новые записи двумя способами. Метод New[Имя_таблицы]Row() возвращает новую строку в таблице: DataSetTest ds = new DataSetTest(); Второй способ - это использовать метод Add[Имя_таблицы]Row(), принимающий массив объектов, соответсвующих полям записи: DataSetTest ds = new DataSetTest(); Поиск записиПоиск записи в таблице тоже претерпел изменения. Например, для поиска в таблице Order Details по составному ключу появился метод следующий метод DataSetTest.Order_DetailRow = tblDetails.FindByOrderIDProductID(112233, 456); Также типизированные DataSet поддерживают русские буквы в названиях таблиц и полей таблиц. ds.Статистика.AddСтатистикаRow(15.9, "компания", true ); Передача обновлений в БД Для передачи изменений в БД используется объекты DataAdapter. Для создания логики обновления БД можно использовать один из трех вариантов: Ручное конфигурирование DataAdapter DataAdapter имеет 3 свойства для передачи изменений в БД: InsertCommand, UpdateCommand и DeleteCommand. Значения этих свойства должны быть заданы до вызова метода DataAdapter.Update() с учетом того, какие изменения были внесены в DataSet. Когда метод Update() добавляет, обновляет или удаляет строки в таблице, он вызывает соответствующую команду. string conn = "Provider = SQLSQL; Data Source = (local)\\NetSDK; Initial Catalog= Northwind; Trusted_Connection=Yes;"; Подобный подход может применяться и при передаче обновлений в БД при помощи хранимых процедур. Допустим, что имя хранимой процедуры для добавления нового покупателя это spInsertCustomer. Тогда наш код измениться следующим образом: OleDbCommand cmd = new OleDbCommand("spInsertCustomer", conn); Использование CommandBuilder CommandBuilder генерирует SQL запросы обращаясь к БД для получения метаданных о таблицах. Для использования CommandBuilder необходимо выполнение следующих условий: 1. запрос возвращает данные только из одной таблицы; string con ="Provider=SQLOLEDB;Data Source=(local)\\NetSDK;InitialCatalog=Northwind;Trusted_Connection=Yes;"; Использование мастера Data Adapter Configuration Wizard Одно из предназначений мастера - создание логики обновления базы данных. На четвертом шаге мастера по команде Advanced Options выводится диалог, в котором можно указать создавать или нет команды для вставки, обновления и удаления записей в БД. На третьем же шаге работы мастер можно указать способ передачи обновления в БД: с помощью SQL запросов, с помощью существующей хранимой процедуры или создание новой хранимой процедуры. Никаких дополнительный действий для создания логики обновления не нужно.
Страница сайта http://silicontaiga.ru
Оригинал находится по адресу http://silicontaiga.ru/home.asp?artId=6222 |