Опубликован: 05.08.2007 | Доступ: свободный | Студентов: 2200 / 83 | Оценка: 4.47 / 4.09 | Длительность: 20:11:00
ISBN: 978-5-9556-0097-0
Лекция 12:

Методы и свойства объекта DataAdapter. передача изменений в базу данных при помощи объекта Command

Аннотация: Конструктор объекта DataAdapter. Метод Fill. Свойство Table Mappings. Окно QuickWatch. Свойство MissingMappingAction. Свойство MissingSchemaAction. Применение свойства TableMappings для помещения в DataSet нескольких таблиц. Изменение записей. Создание объектов SqlCommand для передачи изменений в базу данных. Создание объектов OleDbCommand для передачи изменений в базу данных

Методы и свойства объекта DataAdapter. передача изменений в базу данных при помощи объекта Command

Конструктор объекта DataAdapter

Существует три способа создания объекта DataAdapter1Здесь и далее под названием "DataAdapter" будут подразумеваться как OleDbDataAdapter, так и SqlDataAdapter.: перетаскивание из окна Toolbox элемента DataAdapter, перетаскивание из окна Server Explorer определенного подключения к базе данных или создание в коде. Первые два способа были рассмотрены во "Объекты ADO .NET" , а для программного создания можно использовать один из четырех конструкторов, приведенных в таблице 12.1.

Таблица 12.1. Конструктор класса DataAdapter
Вид Описание
1 public DataAdapter () Конструктор по умолчанию
2 public DataAdapter (string commandText, string connectionString) Первый параметр представляет собой свойство CommandText объекта Command. В свою очередь, объект Command представляется свойством SelectCommand объекта DataAdapter. Второй параметр - строка подключения к базе данных ConnectionString
3 public DataAdapter (string commandText, Connection connection) Первый параметр - свойство CommandText объекта Command, второй - объект класса Connection
4 public DataAdapter (Command command) В качестве параметра передается проинициализированный объект класса Command

В "Элементы работы с базами данных" у нас был проект ConnectionSQL. Скопируйте его папку и переименуйте в "ConstructorDA". В классе формы мы объявляли строки СommandText и СonnectionString:

string commandText = "SELECT CustomerID, CompanyName,
 ContactName, ContactTitle, Address, City, Region," +
 " PostalCode, Country, Phone, Fax FROM Customers";
string connectionString = "workstation id=7EA2B2F6068D473;integrated
 security=SSPI;data sou" + 
 "rce=\"(local)\";persist security info=False;initial
 catalog=NorthwindCS";

Для первого варианта таблицы 12.1 конструктор2На этой странице очень часто встречается слово "конструктор" - не спутайте конструктор объекта DataAdapter с конструктором формы, который имеет вид: public Form1() {//Содержимое конструктора формы} формы будет иметь следующий вид:

public Form1()
{			
	InitializeComponent();
	SqlConnection conn = new SqlConnection();
	conn.ConnectionString = connectionString;
	SqlCommand myCommand = new SqlCommand();
	myCommand.Connection = conn;
	myCommand.CommandText = commandText;
	SqlDataAdapter dataAdapter = new SqlDataAdapter();
	dataAdapter.SelectCommand = myCommand;
	DataSet ds = new DataSet();
	conn.Open();
	dataAdapter.Fill(ds, "Customers");
	dataGrid1.DataSource = ds.Tables["Customers"].DefaultView;
	conn.Close();
}

При выполнении метода Fill будет устанавливаться соединение с базой данных на время извлечения данных. Здесь методы Open и Close объекта conn являются необязательными - другими словами, метод Fill сам откроет и закроет соединение, когда ему будет нужно. Однако оставим их для наглядности. Весь код представляется нам уже достаточно знакомым.

Во втором варианте конструктор формы будет выглядеть так:

public Form1()
{			
	InitializeComponent();
	SqlConnection conn = new SqlConnection();
	conn.ConnectionString = connectionString;
	//SqlCommand myCommand = new SqlCommand();
	//myCommand.Connection = conn;
	//myCommand.CommandText = commandText;
	SqlDataAdapter dataAdapter =
	 new SqlDataAdapter(commandText, connectionString);
	//dataAdapter.SelectCommand = myCommand;
	DataSet ds = new DataSet();
	conn.Open();
	dataAdapter.Fill(ds, "Customers");
	dataGrid1.DataSource =
	 ds.Tables["Customers"].DefaultView;
	conn.Close();
}

Здесь, по сути, мы отказались от применения экзмепляра myCommand класса SqlCommand. Внимательно посмотрите на закомментированные фрагменты: объект myCommand вводился для определения строки commandText и опосредованно - через объект conn строки connectionString. Применяя конструктор объекта dataAdapter, в котором задаются обе эти строки, мы делаем ненужным введение объекта myCommand для этой же цели. Для других задач, например, для запуска хранимой процедуры, объект myCommand может понадобиться. Здесь также можно отказаться от объекта conn, если предоставить методу Fill самому открывать и закрывать соединение:

public Form1()
{	
//SqlConnection conn = new SqlConnection();
//conn.ConnectionString = connectionString;
//SqlCommand myCommand = new SqlCommand();
//myCommand.Connection = conn;
//myCommand.CommandText = commandText;
SqlDataAdapter dataAdapter = new SqlDataAdapter(commandText, connectionString);
//dataAdapter.SelectCommand = myCommand;
DataSet ds = new DataSet();
//conn.Open();
dataAdapter.Fill(ds, "Customers");
dataGrid1.DataSource = ds.Tables["Customers"].DefaultView;
//conn.Close();
}

Наконец, значения строк commandText и connectionString можно задавать прямо в конструкторе, тогда их не нужно объявлять в классе формы:

public Form1()
{
//SqlConnection conn = new SqlConnection();
//conn.ConnectionString = connectionString;
//SqlCommand myCommand = new SqlCommand();
//myCommand.Connection = conn;
//myCommand.CommandText = commandText;
SqlDataAdapter dataAdapter =
 new SqlDataAdapter("SELECT CustomerID, CompanyName,
 ContactName, ContactTitle, Address, City, Region," +
 "PostalCode, Country, Phone, Fax FROM Customers",
 "workstation id=7EA2B2F6068D473;integrated security=SSPI;data sou" +
 "rce=\"(local)\";persist security
 info=False;initial catalog=NorthwindCS");
//dataAdapter.SelectCommand = myCommand;
DataSet ds = new DataSet();
//conn.Open();
dataAdapter.Fill(ds, "Customers");
dataGrid1.DataSource = ds.Tables["Customers"].DefaultView;
//conn.Close();
}

Наилучшим способом управления данными в цепочке "несколько объектов DataTable объекта DataSet - несколько таблиц в базе данных" является создание отдельных объектов DataAdapter для каждого экземпляра DataTable. Представим себе, что наш DataSet состоит из десяти таблиц (представленных соответствующими объектами DataTable ). Нам понадобится десять экземпляров DataAdapter для управления данными. Если эти десять экземпляров мы будем создавать вторым конструктором, куда подаются строки запроса и подключения, то в результате появятся десять независимых объектов класса Connection, одинаковых по своей сути. Производительность такого приложения будет низкой.

Чтобы решить эту проблему, лучше применить третий вариант конструктора для создания адаптера, принимающего строку запроса и объект Connection. Следующий фрагмент кода создает два объекта DataAdapter, использующих один объект Connection:

public Form1()
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = connectionString;
//SqlCommand myCommand = new SqlCommand();
//myCommand.Connection = conn;
//myCommand.CommandText = commandText;
SqlDataAdapter dataAdapter1 = new SqlDataAdapter(commandText1, conn);
//Создаем второй экземпляр dataAdapter2 класса DataAdapter
//SqlDataAdapter dataAdapter2 = new SqlDataAdapter(commandText2, conn);
//dataAdapter.SelectCommand = myCommand;
DataSet ds = new DataSet();
conn.Open();
dataAdapter1.Fill(ds, "Customers");
//Используем второй экземпляр dataAdapter2 для заполнения даными
//dataAdapter2.Fill(ds, "Customers");
dataGrid1.DataSource = ds.Tables["Customers"].DefaultView;
conn.Close();
}

В качестве строк commandText1 и commandText2 применяется исходная строка commandText, в которой разделили выбираемые поля пополам:

string commandText1 = "SELECT CustomerID,
 CompanyName, ContactName, ContactTitle FROM Customers";
string commandText2 = "SELECT Address, City, Region, PostalCode,
 Country, Phone, Fax FROM Customers";

Конечно же, в конструкторе можно передать значения этих строк непосредственно:

SqlDataAdapter dataAdapter1 = new SqlDataAdapter("SELECT CustomerID,
 CompanyName, ContactName, ContactTitle FROM Customers", conn);
//Создаем второй экземпляр dataAdapter2 класса DataAdapter
//SqlDataAdapter dataAdapter2 =
// new SqlDataAdapter("SELECT Address, City, Region, PostalCode,
// Country, Phone, Fax FROM Customers", conn);

Запускаем приложение. Выводится первая половина таблицы Customers, соответствующая запросу commandText1 (рис. 12.1, А). Изменим применяемый объект DataAdapter с помощью комментирования - выводится запрос commandText2 (рис. 12.1, Б).

 Создание двух объектов DataAdapter, A - содержимое первого запроса (commandText1), Б - содержимое второго запроса (commandText2)

увеличить изображение
Рис. 12.1. Создание двух объектов DataAdapter, A - содержимое первого запроса (commandText1), Б - содержимое второго запроса (commandText2)

Четвертый способ создания конструктора представляет собой включение объекта Command:

public Form1()
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = connectionString;
SqlCommand myCommand = new SqlCommand();
myCommand.Connection = conn;
myCommand.CommandText = commandText;
SqlDataAdapter dataAdapter = new SqlDataAdapter(myCommand);
//dataAdapter.SelectCommand = myCommand;
DataSet ds = new DataSet();
conn.Open();
dataAdapter.Fill(ds, "Customers");
dataGrid1.DataSource = ds.Tables["Customers"].DefaultView;
conn.Close();
}

Какой из этих способов лучше всего использовать? Трудно дать универсальную рекомендацию - в каждом конкретном случае наиболее подходящим может быть один из этих способов.

В программном обеспечении к курсу вы найдете приложение Constructor DA (Code\Glava6 ConstructorDA).