- •Поставщики данных ado.Net
- •Для создания набора данных
- •Создание объектов Connection sql Server
- •Создание объектов Connection odbc
- •Пул подключения
- •Разработка приложений с многодокументным интерфейсом
- •Создание родительской формы
- •Создание дочерних форм
- •Работа с потоками
- •Синхронизация потоков
- •Взаимодействие потоков
- •Создание потоков
- •Элемент управления webBrowser
- •Работа с документами в элементе управления webBrowser
- •Создание браузера
- •Работа с xml документами
- •Чтение содержимого xml
- •Запись xml документа
- •Чтение xml в dom
Пул подключения
Организация пулов соединений позволяет существенно улучшить производительность и масштабируемость приложения. Благодаря пулу подключений становится возможным повторное использование существующих подключений. Типичные приложения используют одни и те же объекты Connection для непрерывного извлечения и обновления бд. Пул подключений устраняет необходимость непрерывного создания и удаления подключений к бд.
Поставщик данных .NET Framework для OLE DB автоматически создает пулы соединений, используя пулы сеанса OLE DB. Аргументы строки соединения могут использоваться для включения или отключения служб OLE DB, включая службы пулов. Например, следующая строка соединения отключает пулы сеанса OLE DB и автоматическое прикрепление транзакций.
Provider=SQLOLEDB;OLE DB Services=-4;Data Source=localhost;Integrated Security=SSPI;
Рекомендуется всегда закрывать или удалять соединение при завершении работы, чтобы вернуть его в пул. Соединения, которые явно не закрыты, нельзя вернуть в пул.
Пулы соединений поставщика данных .NET Framework для ODBC управляются диспетчером драйверов ODBC для этого соединения и не зависят от поставщика данных .NET Framework для ODBC.
Чтобы включить или отключить пулы соединений, откройте диалоговое окно Администратор источников данных ODBC в папке «Администрирование» или панели управления. На вкладке Организация пулов соединений можно задать параметры пулов соединений для каждого установленного драйвера ODBC.
Создание и назначение пулов
При открытии соединения создается пул соединений на основе существующего алгоритма сопоставления, связывающего этот пул со строкой соединения. Каждый пул соединений связывается с отдельной строкой соединения. При открытии нового соединения, если строка соединения не соответствует в точности существующему пулу, создается новый пул.
После создания пулы соединений не освобождаются, пока не завершится активный процесс. На поддержку неактивных или пустых пулов затрачивается очень мало системных ресурсов.
Добавление соединения
Пул соединений создается для каждой уникальной строки соединения. При создании пула создается множество объектов соединения, которые добавляются в пул для удовлетворения требования к минимальному размеру пула. Соединения добавляются в пул по мере надобности, пока не будет достигнут максимальный размер пула. Если достигнут максимальный размер пула, а пригодные соединения недоступны, запрос помещается в очередь. Средство управления пулом соединений обрабатывает эти запросы, перераспределяя соединения по мере их освобождения. Соединения освобождаются обратно в пул при закрытии или ликвидации.
Удаление соединений
Средство управления пулом соединений удаляет соединение из пула после длительного бездействия соединения, или если обнаруживает, что соединение с сервером разорвано. При обнаружении соединения, которое больше не имеет связи с сервером, оно помечается как недействительное. Средство управления пулом соединений периодически просматривает пулы соединений в поиске объектов, освобожденных в пул и маркированных как недопустимые. Эти соединения удаляются.
Управление опциями пула подключения
Connection Lifetime (0) - Если соединение возвращается в пул, время его создания сравнивается с текущим временем, и соединение уничтожается, если этот промежуток времени (в секундах) превышает значение, заданное параметром Connection Lifetime. Эта возможность полезна в кластеризованных конфигурациях для принудительной балансировки нагрузки между выполняющимся сервером и сервером, только что переведенным в оперативный режим. Значение ноль (0) означает максимальное время ожидания для соединений в пуле.
Enlist ('true') - При значении true средство управления пулом автоматически прикрепляет соединение к текущему контексту транзакции потока создания, если контекст транзакции существует.
Max Pool Size (100) - Максимальное число разрешенных соединений в пуле.
Min Pool Size (0) - Минимальное число поддерживаемых соединений в пуле.
Pooling (true) - При значении true соединение извлекается из соответствующего пула или при необходимости создается и добавляется в соответствующий пул.
Элемент <connectionStrings>
Возвращает или задает строку, используемую для открытия базы данных.
Строка соединения представляет собой нормальное представление строка, которая содержит информацию подключения к базе данных, чтобы установить соединение между базой данных и приложением. Строка соединения включает в себя такие параметры, как имя драйвера, имя сервера и базы данных, а также безопасность информации, такой как имя пользователя и пароль.
Обычно поставщики данных использовать соединение строка, содержащая набор параметров для установления соединения с базой данных через приложения. . NET Framework обеспечивает в основном три поставщиками данных: Microsoft SQL Server, OLEDB, ODBC.
Microsoft SQL Server строки соединения
connetionString = "Data Source = ServerName; Initial Catalog = Databasename;
User ID = имя пользователя; Password = пароль "
Поставщик данных OLEDB Строка соединения
connetionString = "Provider = Microsoft.Jet.OLEDB.4.0;
Data Source = yourdatabasename.mdb; "
Строка подключения ODBC
connetionString = "Driver = {Microsoft Access Driver (* MDB.)};
DBQ = yourdatabasename.mdb; "
Модель генератора поставщиков данных ADO.NET
Генератор поставщиков данных .NET позволяет создать единую кодовую базу с помощью обобщенных типов доступа к данным. Посредством конфигурационных файлов приложения (и подэлемента <connectionStrings>) можно получить поставщики и строки подключения без необходимости в повторной компиляции или развертывания сборки. Все классы в поставщике данных порождены от одних и тех же базовых классов, которые определены в System.Data.Common:
DbCommand – абстрактный базовый класс для всех объектов команд;
DbConnection - абстрактный базовый класс для всех объектов подключения;
DbAdapter – абстрактный базовый класс для всех объектов адаптеров данных;
DbDataReader - абстрактный базовый класс для всех объектов чтения данных;
DbParametr – абстрактный базовый класс для всех объектов параметров;
DbTransaction – абстрактный базовый класс для всех объектов транзакций.
Using System.Data;
System.Data.Common;
System.Configuration;
Namespace DataEx
{class Programm
{static DbConnection Connection (string name) //1
{ConnectionStringSettings settings=ConfigurationManager.ConnectionStrings[name]; //2
DBConnection conn=factory.CreateConnection();//3
conn.ConnectionString=settings.ConnectionString; //4
return conn;
}
svM()
{DbConnection conn = Connection (“MyConnection”);
Conn.Open();
C.W.(“подключение к серверу прошло успешно!”);
Conn.Close();
}}}
1)
ConnectionStringSettings – класс, который представляет собой отдельную строку подключения в разделе строк подключения файла конфигурации.
ConfigurationManager – класс, предоставляющий доступ к файлом конфигурации для клиентских приложений, не может быть наследован.
ConnectionStrings – свойство, возвращающее информацию о заданной строке подключения.
2)
DbProviderFactory - класс, предоставляющий методы для создания экземпляров классов-поставщиков, реализующих источник данных.
DbProviderFactories – класс, который представляет набор статических методов для создания одного или нескольких экземпляров классов System.Data.Common.DbProviderFactory.
GetFactory() – метод, возвращающий экземпляр класса System.Data.Common.DbProviderFactory.
Следовательно поле factory, позволяет создать единую кодовую базу для всех поставщиков данных.
3) создание соединения;
4) получение строки подключения.
Эффективное использование соединений
Незакрытое соединение может полностью блокировать доступ других пользователей к целым множествам таблиц, нанося огромный ущерб производительности приложения. Закрытие соединений базы данных должно считаться обязательным. Способы осуществления корректной работы: обработка исключительных ситуаций (try…catch…finally) и оператор using.
using (SqlConnection cn = new SqlConnection())
{
cn.ConnectionString = connect.ConnectionString;
try
{
//Открыть подключение
cn.Open();
}
catch (SqlException ex)
{
// Протоколировать исключение
Console.WriteLine(ex.Message);
}
finally
{
// Гарантировать освобождение подключения
cn.Close();
}
}
ExecuteReader()
Метод ExecuteReader() выполняет команду и возвращает типизированный объект-читатель данных, в зависимости от используемого поставщика. Возвращенный объект может применяться для итерации по возвращенным записям.
string strSQL = "SELECT * FROM Inventory";
SqlCommand myCommand = new SqlCommand(strSQL, cn);
SqlDataReader dr = myCommand.ExecuteReader();
while (dr.Read())
Console.WriteLine("ID: {0} Car Pet Name: {1}",dr[0],dr[3]);
Select * From имя_таблицы
ExecuteNonQuery ()
Метод ExecuteNonQuery() обычно используется для операторов UPDATE, INSERT или DELETE, где единственным возвращаемым значением является количество обработанных строк. Однако метод может вернуть результаты, если осуществляется вызов хранимой процедуры с выходными параметрами.
string strSQL = "UPDATE Customers SET LastName = 'Johnson' WHERE LastName = 'Walton'";
SqlCommand myCommand = new SqlCommand(strSQL, cn);
int i = myCommand.ExecuteNonQuery();
команда вставки: Insert Into имя_таблицы (Имя столбца1, Имя столбца 2, …) Values (‘Значение1’, ‘Значение 2’…)
команда удаления: Delete From имя_таблицы where имя_любого_столбца = ‘Его значение’
команда удаления: Update имя_таблицы Set имя_ столбца = ‘значение’ where имя_столбца = ‘значение’
Транзакции баз данных
Транзакция — это набор операций в базе данных, которые должны быть либо все выполнены, либо все не выполнены. Транзакции применяются для обеспечения безопасности, достоверности и согласованности данных в таблице. Транзакции важны в ситуациях, когда операция базы данных предусматривает взаимодействие с несколькими таблицами или хранимыми процедурами (либо с комбинацией атомарных объектов базы данных). Классическим примером транзакции может служить процесс перевода денежных средств с одного банковского счета на другой.
Рассмотрим объекты транзакции, которые имеются в поставщиках данных ADO.NET; все они являются производными от DBTransaction и реализуют интерфейс IDbTransaction.
public interface IDbTransaction : IDisposable
{
IDbConnection Connection { get; }
IsolationLevel IsolationLevel { get; }
void Commit();
void Rollback ();
}
Обратите внимание на свойство Connection, которое возвращает ссылку на объект подключения, инициировавший текущую транзакцию. Метод Commit () вызывается, если все операции в базе данных завершились успешно. При этом все ожидающие изменения фиксируются в хранилище данных. Метод Rollback () можно вызвать при возникновении исключения времени выполнения, тем самым сообщив СУБД, что все ожидающие изменения следует отменить и оставить первоначальные данные без изменений. Вызов Rollback() без аргументов приводит к отмене всех ожидающих изменений. Свойство IsolationLevel объекта транзакции позволяет указать степень защиты текущей транзакции от действий со стороны параллельных транзакций. В типе SqlTransaction определен дополнительный член по имени Save (), который предназначен для определения точек сохранения. Эта концепция позволяет откатить неудачную транзакцию до указанной точки, не выполняя откат всей транзакции.
Автономный уровень ADO.NET
За счет использования автономных типы становится возможным моделирование реляционных данных с помощью модели объектов, находящихся в памяти. Кроме простого моделирования табличных данных, состоящих из строк и столбцов, типы в пространстве имен System.Data позволяют представлять отношения между таблицами, ограничения столбцов, первичные ключи, представления и другие примитивы баз данных. К смоделированным данным можно применять фильтры, отправлять запросы в памяти и сохранять (или загружать) данные в формате XML и в двоичном формате. И все это можно делать, даже не подключаясь к СУБД — достаточно загрузить данные из локального XML-файла или программным образом построить объект DataSet. Автономные типы действительно можно бьшо бы использовать без подключения к базе данных, но обычно все-таки применяются подключения и объекты команд.
Адаптер данных ADO.NET
Адаптер данных (расширяющий абстрактный тип DbDataAdapter) выбирает и обновляет данные. В отличие от подключенного уровня, данные, полученные через адаптер данных, не обрабатываются с помощью объектов чтения данных. Вместо этого объекты адаптеров пересылают данные между вызывающим процессом и источником данных с помощью объектов
DataSet (точнее, объектов DataTable в DataSet).
Объект адаптера данных конкретного поставщика данных автоматически обслуживает подключение к базе данных. Для повышения масштабируемости адаптеры данных удерживают подключение открытым в течение минимально возможного времени. Как только вызывающий процесс получит объект DataSet, вызывающий уровень полностью отключается от базы данных и остается с локальной копией удаленных данных. Теперь в нем можно вставлять, удалять или обновлять строки в указанном объекте DataTable, но физическая база данных не будет обновлена до тех пор, пока вызывающий процесс явно не передаст DataTable из DataSet адаптеру данных для обновления. По сути, объекты DataSet имитируют постоянное подключение клиентов, хотя на самом деле они работают с находящейся в памяти базой данных.
Роль объектов DataSet
Тип DataSet представляет собой контейнер для любого количества объектов DataTable, каждый из которых содержит коллекцию объектов DataRow и DataColumn. Объект адаптера данных конкретного поставщика данных автоматически обслуживает подключение к базе данных. Для повышения масштабируемости адаптеры данных держат подключение открытым минимально возможное время. Как только вызывающий процесс получит объект DataSet, вызывающий уровень полностью отключается от базы данных и остается с локальной копией удаленных данных.
Теперь в нем можно вставлять, удалять или изменять строки различных объектов DataTable, но физическая база данных не обновляется, пока вызывающий процесс явно не передаст DataSet адаптеру данных для обновления. По сути, объекты DataSet имитируют постоянное подключение клиентов, хотя на самом деле они работают с находящейся в памяти базой данных:
Объект DataSet является представлением реляционных данных в памяти. DataSet — это класс, который внутренне поддерживает три строго типизированных коллекции: DataTableCollection, DataRelationCollection, PropertyCllection.
Свойство Tables класса DataSet предоставляет доступ к коллекции DataTableCollection, которая содержит отдельные объекты DataTable. Так как DataSet является автономной версией схемы базы данных, его можно использовать для программного представления отношений “родительский-дочерний” между таблицами. С применением типа DataRelation можно создать отношение между двумя таблицами для моделирования ограничения внешнего ключа. Затем с помощью свойства Relations этот объект можно добавить в коллекцию DataRelationCollection. Свойство ExtendedProperties предоставляет доступ к объекту PropertyCollection, который позволяет связать с DataSet любую дополнительную информацию в виде пар “имя/значение”.
Свойства:
CaseSensitive - Указывает, чувствительны ли к регистру букв сравнения строк в объектах DataTable. По умолчанию равно false (сравнения строк выполняются без учета регистра букв)
DataSetName - Задает понятное имя для данного DataSet. Обычно это значение передается через параметр конструктора
EnforceConstraints - Задает или получает значение, определяющее, применяются ли правила ограничений при выполнении любых обновлений (по умолчанию равно true)
HasErrors - Получает значение, определяющее, имеются ли ошибки в любой строке любого из объектов DataTable данного DataSet
RemotingFormat - Позволяет определить, как DataSet должен сериализовать свое содержимое (в виде двоичного файла или, по умолчанию, XML)
Методы:
AcceptChanges() - Отправляет все изменения, выполненные в данном DataSet после его загрузки или последнего вызова AcceptChanges()
Clear() - Полностью очищает DataSet, удаляя все строки в каждом DataTable
Clone() - Клонирует структуру DataSet, в том числе и всех DataTable, а также все отношения и ограничения
Copy() - Копирует структуру и данные текущего DataSet
GetChanges() - Возвращает копию DataSet, содержащую все изменения, которые были выполнены в данном DataSet после его загрузки или последнего вызова AcceptChanges(). У этого метода есть перегруженные варианты, которые позволяют получить только новые строки, только измененные строки или только удаленные строки
HasChanges() - Выдает, содержит ли DataSet изменения, т.е. новые, удаленные или измененные строки
Merge() - Объединяет данный DataSet с указанным DataSet
ReadXml() - Позволяет определить структуру объекта DataSet и заполнить его данными на основе XML-схемы и данных из потока
RejectChanges() - Отменяет все изменения, которые были выполнены в данном DataSet после его загрузки или последнего вызова AcceptChanges()
WriteXml() - Позволяет записать содержимое DataSet в поток
static void Main(string[] args)
{
// Создание DataSet
DataSet carsInvenoryDS = new DataSet("Car Inventory");
carsInvenoryDS.ExtendedProperties["TimeStamp"] = DateTime.Now;
carsInvenoryDS.ExtendedProperties["DataSetID"] = Guid.NewGuid();
carsInvenoryDS.ExtendedProperties["Company"] = "Мой магазин";
Console.ReadLine();
}
Работа с DataSet
Объект DataSet не особенно интересен, если он не содержит хоть немного объектов DataTable. Глобально уникальный идентификатор (globally unique identifier — GUID) представляет собой статически уникальное 128-битовое число.
static void Main(string[] args)
{
// Создать объект DataSet и добавить несколько свойств.
DataSet carsInventoryDS = new DataSet("Car Inventory");
carsInventoryDS.ExtendedProperties["TimeStamp"] = DateTime.Now;
carsInventoryDS.ExtendedProperties["DataSetID"] = Guid.NewGuid() ;
carsInventoryDS.ExtendedProperties["Company"] = "Mikko's Hot Tub Super Store";
}
Guid применяется для создания статически уникального 128-битного числа.
Using System;
System.Data;
namespace DataEx
{
class Programm
{
static void Main ()
{
Console.WriteLine (“*****Работа с объектами DataSet*****\n”);
//Создание объекта DataSet и добавление нескольких свойств
DataSet carsInventory DS = new DataSet (“Car Inventory”);
carsInventoryDS.ExtendedProperties[“TimeStamp”]=DataTime.Now;
carsInventoryDS.ExtendedProperties[“DataSetID”]=Guid.NewGuid();
carsInventoryDS.ExtendedProperties[“Company”]=”супер-гипер-магазин Mikko”;
}}}
Роль объектов DataColumn
Тип DataColumn представляет один столбец внутри объекта DataTable. Набор всех объектов DataColumn, содержащихся в заданном объекте DataTable, представляет информацию схемы таблицы. После создания объектов DataColumn они обычно добавляются в коллекцию столбцов типа DataTable (с помощью свойства Columns). Любому столбцу в таблице базы данных можно назначить набор ограничений (сконфигурировать как первичный ключ, присвоить стандартное значение, разрешить только чтение и т.п.). Каждый столбец таблицы должен отображаться на лежащий в основе тип данных. Класс DataColumn имеет ряд свойств для точного конфигурирования таких аспектов.
Свойства:
AllowDBNull - Указывает, может ли данный столбец содержать пустые значения. По умолчанию содержит значение true
AutoIncrement, AutoIncrementSeed, AutoIncrementStep - Применяются для настройки поведения автоинкремента для данного столбца. Это может оказаться удобным, если нужно обеспечить уникальность значений в этом DataColumn (например, если он содержит первичные ключи). По умолчанию DataColumn не поддерживает автоинкрементное поведение
Caption - Задает или получает заголовок, который должен отображаться для данного столбца. Это позволяет определить более наглядные варианты для имен столбцов в базе данных
ColumnMapping - Определяет представление DataColumn при сохранении DataSet в виде XML-документа с помощью метода DataSet.WriteXml(). Можно указать, что столбец данных должен быть записан как XML-элемент, XML-атрибут, простое текстовое содержимое, либо его следует полностью проигнорировать
ColumnName - Задает или получает имя столбца из коллекции Columns (т.е его внутреннее представление в DataTable). Если не занести значение в ColumnName явно, то по умолчанию там находится слово "Column" с числовыми суффиксами по формуле n+1 (т.е. Column1, Column2, Column3 и т.д.)
DataType - Определяет тип данных (логический, строковый, с плавающей точкой и т.д.), хранящихся в данном столбце
DefaultValue - Задает или получает значение по умолчанию, заносимое в данный столбец при вставке новых строк
Expression - Задает или получает выражение для фильтрации строк, вычисления значения столбца или создания агрегированного столбца
Ordinal - Задает или получает числовое положение столбца в коллекции Columns, содержащейся в DataTable
Readonly - Определяет, предназначен ли данный столбец только для чтения после добавления строки в таблицу. По умолчанию равно false
Table - Получает объект DataTable, содержащий данный DataColumn
Unique - Задает или получает значение, указывающее, должны ли быть уникальными значения во всех строках данного столбца, или допустимы совпадения. При присвоении столбцу ограничения первичного ключа свойство Unique должно содержать значение true
Если нужно создать копию таблицы Inventory из БД DataEx, нужно создать 4 объекта DataColumn по одному для каждого столбца. После создания объектов DataColumn они добавляются в коллекцию столбцов с помощью свойства Colums.
Работа с DataColumn
Необходимо смоделировать столбцы таблицы Inventory. Поскольку столбец CarID будет первичным ключом таблицы, он должен быть сконфигурирован как предназначенный только для чтения, содержащий уникальные значения и не допускающим null (с помощью свойств ReadOnly, Unique и AllowDBNull). Добавьте в класс Program новый метод по имени FillDataSet (), предназначенный для построения четырех объектов DataColumn. Обратите внимание, что этот метод принимает в качестве единственного параметра объект DataSet.
static void FillDataSet(DataSet ds)
{
// Создать столбцы данных, которые отображаются на "реальные"
// столбцы в таблице Inventory из базы данных AutoLot.
DataColumn carIDColumn = new DataColumn("CarID", typeof(int));
carIDColumn.Caption = "Car ID";
carIDColumn.ReadOnly = true;
carIDColumn.AllowDBNull = false;
carIDColumn.Unique = true;
DataColumn carMakeColumn = new DataColumn("Make", typeof(string));
DataColumn carColorColumn = new DataColumn("Color", typeof(string));
DataColumn carPetNameColumn = new DataColumn("PetName", typeof(string));
carPetNameColumn.Caption = "Pet Name";
}
При конфигурировании объекта carIDColumn бьшо присвоено значение свойству Caption. Это позволяет определить строковое значение для отображения при выводе данных, которое может отличаться от имени столбца (имена столбцов в таблицах баз данных обычно более удобны для программирования, чем для отображения).
Смоделируем столбцы таблицы. CarID – первичный столбец
Using System;
System.Data;
namespace DataEx
{
class Programm
{
static void Main ()
{
//создание столбцов данных, соответствующих «реальным» столбцам таблицы Inventory из БД DataExample
DataColumn carIDColumn=new DataColumn (“CarID”, typeof(int));
carIDColumn.Caption=”CarID”;
carIDColumn.ReadOnly=true;
carIDCOlumn.AllowDBNull = false;
carIDColumn.Unique = true;
DataColumn carMakeColumn = new DataColumn (“Make”, typeof(string));
DataColumn carColorColumn = new DataColumn (“Color”, typeof(string));
DataColumn carPetNameColumn = new DataColumn (“PetName”, typeof(string));
carPetNameColumn.Caption = “Друж.Имя”;
}}}
Включение автоинкрементных полей
Одним из аспектов DataColumn, допускающим конфигурирование, является возможность автоинкремента. Автоинкрементное поле используется для обеспечения того, что при добавлении в таблицу новой строки значение этого поля устанавливается автоматически на основе предыдущего значения и шага увеличения. Это удобно, когда нужно гарантировать, что в столбце отсутствуют повторяющиеся. Это поведение управляется свойствами AutoIncrement, AutoIncrementSeed (определение начального значения в столбце) и AutoIncrementStep (указания числа, которое прибавляется для каждого последующего значения).
static void FillDataSet(DataSet ds)
{
DataColumn carIDColumn = new DataColumn("CarID", typeof(int));
carIDColumn.ReadOnly = true;
carIDColumn.Caption = "Car ID";
carIDColumn.AllowDBNull = false;
carIDColumn.Unique = true;
carIDColumn.AutoIncrement = true;
carIDColumn.AutoIncrementSeed = 0;
carIDColumn.AutoIncrementStep = 1;
}
Одним из аспектов DataColumn, доускающим настройку , является автоинкрементность полей. Это удобно, чтобы в каком-то столбце не было повторяющихся полей. AutoIncrementSeed – начальное значение, AutoIncrementStep – для задания числа, которое прибавляется для каждого последующего значения.
13.class Programm
{
static void Main ()
{
DataColumn carIDColumn=new Dataolumn (“CarID”, typeof(int));
carIDColumn.ReadOnly = true;
carIDCOlumn.AllowDBNull = false;
carIDColumn.Unique = true;
carIDColumn.AutoIncrement = true;
carIdColumn.AutoIncrementSeed=0;
carID.AutoIncrementStep = 1;
…
}}}
Добавление объектов DataColumn в DataTable
Обычно тип DataColumn не применяется как обособленная сущность, а вставляется в соответствующий объект DataTable.
static void FillDataSet(DataSet ds) :
{
// Добавить объекты DataColumn в DataTable.
DataTable inventoryTable = new DataTable("Inventory");
inventoryTable.Columns.AddRange(new DataColumn[] { carIDColumn, carMakeColumn, carColorColumn, carPetNameColumn });
Теперь объект DataTable содержит четыре объекта DataColumn, которые представляют схему находящейся в памяти таблицы Inventory. Но пока эта таблица не содержит данных и не входит в коллекцию таблиц, обслуживаемых DataSet.
Работа с объектами DataRow
Коллекция объектов DataRow представляет конкретные данные в таблице.
HasErrors, GetColumnsInError(), GetColumnError(), ClearErrors(), RowError - Свойство HasErrors возвращает логическое значение, означающее наличие ошибок. Если они есть, то метод GetColumnsInError() позволяет получить ошибочные столбцы, а метод GetColumnError() — получить описание ошибки. Аналогично, метод ClearErrors() удаляет из строки всю информацию об ошибках. Свойство RowError позволяет создать текстовое описание ошибки для данной строки
ItemArray - Свойство, задающее или получающее все значения столбцов строки в виде массива объектов
RowState - Свойство, позволяющее зафиксировать текущее состояние объекта DataRow в содержащем его DataTable с помощью значений перечисления RowState (новый, измененный, не измененный или удаленный)
Table - Свойство, позволяющее получить ссылку на объект DataTable, содержащий данный объект DataRow
AcceptChanges(), RejectChanges() - Методы для фиксации или отмены всех изменений, выполненных в данной строке с момента последнего вызова AcceptChanges()
BeginEdit(), EndEdit(), CancelEdit() - Методы, начинающие, заканчивающие или отменяющие операцию редактирования для объекта DataRow
Delete() - Метод, помечающий данную строку для удаления при вызове метода AcceptChanges()
IsNull() - Метод, получающий значение, которое указывает, содержит ли заданный столбец пустое значение
Создавать экземпляр этого типа напрямую невозможно, т.к. в нем нет открытых конструкторов:
DataRow r = new DataRow();
Вместо этого новый объект DataRow получается из указанного объекта DataTable. Метод DataTable.NewRow() позволяет получить очередную область в таблице, после чего можно заполнить каждый столбец новыми данными с помощью индексатора типа. При этом можно указать либо строковое имя, назначенное объекту DataColumn, либо номер его позиции (начинающийся с нуля):
static void FillDataSet(DataSet ds)
{
// Добавить несколько строк в таблицу Inventory.
DataRow carRow = inventoryTable.NewRow();
carRow["Make"] = "BMW";
carRow["Color"] = "Black";
carRow["PetName"] = "Hamlet";
inventoryTable.Rows.Add(carRow);
carRow = inventoryTable.NewRow();
// Столбец 0 - это автоинкрементное поле идентификатора,
// поэтому начать заполнение со столбца 1.
carRow[l] = "Saab";
carRow[2] = "Red";
carRow[3] = "Sea Breeze";
inventoryTable.Rows.Add(carRow);
}
В случае передачи методу индексатора типа DataRow недопустимого имени столбца или позиции во время выполнения сгенерируется исключение. К этому моменту имеется один объект DataTable, содержащий две строки. Разумеется, этот общий процесс можно повторить, чтобы создать нужное количество объектов DataTable, определить схему и заполнить данными.
Свойство RowState применяется для программной идентификации множества всех строк таблицы, которые изменили свое первоначальное значение, были вставлены и т.п. Это свойство может принимать любое значение из перечисления DataRowState:
Added - Строка была добавлена в DataRowCollection, a AcceptChanges() еще не был вызван
Deleted - Строка была помечена для удаления с помощью метода Delete() класса DataRow, a AcceptChanges() еще не был вызван
Detached - Строка была создана, но не включена ни в какой DataRowCollection. Объект DataRow находится в этом состоянии после его создания, но до занесения в какую-либо коллекцию, либо после исключения из коллекции
Modified - Строка была изменена, a AcceptChanges() еще не был вызван
Unchanged - Строка не была изменена после последнего вызова AcceptChanges()
Кроме отслеживания текущего состояния строк с помощью свойства RowState, объект DataRow отслеживает три возможные версии содержащихся в нем данных с помощью свойства DataRowVersion. Свойство DataRowVersion может содержать:
Current - Представляет текущее значение строки, даже после выполнения изменений
Default - Стандартный вариант DataRowState. Если значение DataRowState равно Added, Modified или Deleted, то стандартной версией является Current. Для значения DataRowState, равного Detached, стандартной версией является Proposed
Original - Представляет значение, первоначально вставленное в DataRow, или значение при последнем вызове AcceptChanges()
Proposed - Значение строки, редактируемой в настоящий момент с помощью вызова BeginEdit()
Работа с адаптером данных
Адаптер данных — это класс, применяемый для заполнения DataSet объектами DataTable; этот класс также может отправлять измененные объекты DataTable обратно базе данных для обработки.
Основные члены класса DbDataAdapter:
Fill () – Выполняет SQL-команду SELECT (указанную в свойстве SelectCommand) для запроса у базы данных и загрузки полученных данных в объект DataTable
SelectCommand, InsertCommand, UpdateCommand, DeleteCommand - Устанавливают SQL-команды, отправляемые в хранилище данных, когда вызываются методы Fill () и Update ()
Update () - Выполняет SQL-команды INSERT, UPDATE и DELETE (указанные в свойствах InsertCommand, UpdateCommand и DeleteCommand) для сохранения в базе данных изменений, произведенных в DataTable
Свойства адаптера данных: SelectCommand, InsertCommand, UpdateCommand, DeleteCommand. При создании объекта адаптера данных для конкретного поставщика данных можно передать строку с текстом команды, используемом объектом команды SelectCommand.
После должной настройки каждого из 4 команд можно вызвать метод Fill() и получить объект DataSet (или отдельный DataTable).
Для сохранения измененного объекта необходимо вызвать Update (). Для адаптера данных не нужно открывать или закрывать подключение к БД, это делается автоматически. Однако нужно передать объект подключения или строку подключения для сообщения информации с какой БД нужно взаимодействовать.
static void Main(string[] args)
{
// Жестко закодированная строка соединения.
string cnStr = "Integrated Security = SSPI;Initial Catalog=AutoLot;" +"Data Source=(local)\SQLEXPRESS";
// Объект DataSet создается вызывающим процессом.
DataSet ds = new DataSet("AutoLot");
// Указать адаптеру текст команды Select и строку соединения.
SqlDataAdapter dAdapt = new SqlDataAdapter("Select * From Inventory", cnStr);
// Заполнить DataSet новой таблицей по имени Inventory.dAdapt.Fill(ds, "Inventory");
// Отобразить содержимое DataSet с использованием вспомогательного
// метода, созданного ранее в данной главе.
PrintDataSet(ds);
Console.ReadLine();
}
