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

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

Свойство MissingMappingAction

В рассмотренных выше примерах мы определяли названия полей в объекте DataSet для всех заголовков таблицы, извлекаемой из базы данных. Таблица в базе данных может измениться, например, в нее будут добавлены столбцы, которых нет в свойстве TableMappings. Что произойдет в этом случае? Объект DataAdapter имеет свойство MissingMappingAction, предназначенное для таких ситуаций. Его значение по умолчанию - Passthrough (рис. 12.10).

 Свойство MissingMappingAction объекта DataAdapter в приложении VisualTableMappings

Рис. 12.10. Свойство MissingMappingAction объекта DataAdapter в приложении VisualTableMappings

Для того чтобы разобраться с этим свойством, откроем приложение ProgrammTableMappings, закомментируем пару столбцов в определении TableMappings и добавим программно свойство MissingMappingAction:

...
DataColumnMapping[] dcMappings = 
	{
	new DataColumnMapping("CustomerID", "Номер_клиента"),
//new DataColumnMapping("CompanyName", "Компания"),
//new DataColumnMapping("ContactName", "Имя"),
	new DataColumnMapping("ContactTitle", "Должность"),
	new DataColumnMapping("Address", "Адрес"),
	new DataColumnMapping("City", "Город"),
	new DataColumnMapping("Region", "Регион"),
	new DataColumnMapping("PostalCode", "Индекс"),
	new DataColumnMapping("Country", "Страна"),
	new DataColumnMapping("Phone", "Телефон"),
	new DataColumnMapping("Fax", "Факс"),
	};

dtMapping.ColumnMappings.AddRange(dcMappings);
dataAdapter.TableMappings.Add(dtMapping);

dataAdapter.MissingMappingAction = MissingMappingAction.Passthrough;
...

Запускаем приложение. Мы убрали столбцы "Компания" и "Имя" - при значении по умолчанию Passthrough свойства MissingMappingAction в DataSet помещаются поля с их оригинальными названиями (рис. 12.11):

 Вид таблицы при значении Passthrough свойства Missing MappingAction

Рис. 12.11. Вид таблицы при значении Passthrough свойства Missing MappingAction

Изменим значение на Ignore:

dataAdapter.MissingMappingAction = MissingMappingAction.Ignore;

В результате будут игнорироваться столбцы, не указанные в свойстве TableMappings (рис. 12.12):

 Вид таблицы при значении Ignore свойства Missing MappingAction

Рис. 12.12. Вид таблицы при значении Ignore свойства Missing MappingAction

Последнее значение Error:

dataAdapter.MissingMappingAction = MissingMappingAction.Error;

В этом случае сгенерируется исключение, которое может быть перехвачено блоком обработки.

Свойство MissingSchemaAction

Свойство MissingMappingAction позволяет быстро конфигурировать поля извлекаемых данных при использовании свойства TableMappings. А как определять вид данных в других случаях, когда свойство TableMappings не задано? Мы знаем, что если объект DataSet вообще не содержит схемы, DataAdapter выведет ее на основании результатов выполнения запроса - на форме появятся все извлеченные поля. Также вполне возможно, что DataSet будет содержать схему, причем она будет отличаться от структуры извлекаемых данных. В этом случае следует применять свойство MissingSchemaAction объекта DataAdapter, которое может принимать следующие значения:

  • Add - к схеме объекта DataSet будут добавлены все извлекаемые столбцы из базы данных (значение по умолчанию);
  • AddWithKey - к схеме объекта DataSet будут добавлены все извлекаемые столбцы из базы данных. Объект DataAdapter также попытается извлечь из базы данных информацию о ключах и определить первичные ключи заполняемых им объектов DataTable. Кроме того, описание полей, имеющихся в схеме объекта DataSet, может быть заменено на извлеченное из базы данных;
  • Ignore - не входящие в схему объекта DataSet столбцы, извлекаемые из базы данных, игнорируются;
  • Error - при несоответствии схемы объекта DataSet и структуры извлекаемых данных генерируется исключение.

Создайте новое приложение и назовите его "VisualMissingMapping Action". Перетаскиваем на форму элемент управления DataGrid, свойству Dock устанавливаем значение Fill. Из окна Server Explorer перетаскиваем на форму таблицу Customers базы данных MS SQL "Northwind". В окне Toolbox переходим на вкладку Data и добавляем на форму объект DataSet. В появившемся окне Add DataSet выбираем Untyped dataset. Переходим в окно Properties добавленного DataSet, в свойстве Name вводим dsCustomers. Теперь нам предстоит создать схему, содержащую всего одно поле (столбец), которое есть в таблице "Customers" базы данных. Для того чтобы вспомнить названия столбцов, посмотрим на содержимое, которое будет извлекать DataAdapter. Выделяем объект sqlDataAdapter1 и в окне Properties нажимаем на ссылку "Preview Data_" В появившемся окне Data Adapter Preview нажимаем кнопку "Fill Dataset" (рис. 12.13):

 Окно Data Adapter Preview

увеличить изображение
Рис. 12.13. Окно Data Adapter Preview

Обратите внимание на определение размера извлекаемых данных - 37,1 Кб. Создадим поле, соответствующее столбцу CustomerID. Закрываем окно Data Adapter Preview, выделяем объект dsCustomers в окне Properties, в поле свойства Tables нажимаем на кнопку(...). Добавляем объект DataTable ( Name - "dtCustomers", TableName - "Customers" ), в поле свойства Columns нажимаем на кнопку(...). Добавляем объект DataColumn (рис. 12.14) ( Name - "dcCustomerID", ColumnName - "CustomerID" ) - всего один, для вывода только одного поля из таблицы базы данных.

 Объекты DataTable и DataColumn в схеме dsCustomers

увеличить изображение
Рис. 12.14. Объекты DataTable и DataColumn в схеме dsCustomers

В конструкторе формы заполняем объект DataSet и выводим данные на форму:

public Form1()
		{
			InitializeComponent();
			sqlDataAdapter1.Fill(dsCustomers);
			dataGrid1.DataSource = dsCustomers;
		}

Запускаем приложение. Несмотря на наличие схемы объекта DataSet, на форму выводятся все данные (рис. 12.15):

 Приложение VisualMissingMappingAction

Рис. 12.15. Приложение VisualMissingMappingAction

Дело в том, что по умолчанию в DataSet добавляются столбцы из базы данных, которых нет в схеме - результат будет в точности такой же, если мы зададим явно свойство MissingSchemaAction со значением Add:

public Form1()
		{
			InitializeComponent();
			sqlDataAdapter1.MissingSchemaAction = MissingSchemaAction.Add;
			sqlDataAdapter1.Fill(dsCustomers);
			dataGrid1.DataSource = dsCustomers;
		}

Изменим значение на Ignore:

sqlDataAdapter1.MissingSchemaAction = MissingSchemaAction.Ignore;

Теперь данными заполняется только одно поле, которое было определено в схеме (рис. 12.16):

 Приложение VisualMissingMappingAction. Значение Ignore свойства MissingSchemaAction

Рис. 12.16. Приложение VisualMissingMappingAction. Значение Ignore свойства MissingSchemaAction

Изменим значение на Error:

sqlDataAdapter1.MissingSchemaAction = MissingSchemaAction.Error;

Теперь при запуске появляется исключение - "Пропущен объект DataColumn "CompanyName в DataTable "Customers", соответствующий столбцу в источнике данных CompanyName (рис. 12.17):

 Приложение VisualMissingMappingAction. Значение Error свойства MissingSchemaAction

Рис. 12.17. Приложение VisualMissingMappingAction. Значение Error свойства MissingSchemaAction

Объект DataAdapter, установив связь с источником данных, попытался заполнить DataSet данными, но, не обнаружив второй столбец, сгенерировал исключение (после столбца CustomerID следует Company Name, см рис. 12.13). Это исключение может быть перехвачено блоком обработки.

Наконец, устанавливаем четвертое значение - AddWithKey:

sqlDataAdapter1.MissingSchemaAction = MissingSchemaAction.AddWithKey;

На этот раз приложение заполнилось всеми данными, точно так же, как при значении Add. Какая между ними разница? Запустим приложение SQL Server Enterprise Manager, входящее в пакет Microsoft SQL Server 2000, и просмотрим структуру таблицы Customers в режиме дизайна (рис. 12.18):

 Таблица "Customers" базы данных "Northwind"

Рис. 12.18. Таблица "Customers" базы данных "Northwind"

Поле CustomerID имеет длину 5 символов и, поскольку оно является ключевым, не допускает пустых значений - в столбце Allow Nulls галочки нет. Переходим в код приложения VisualMissingMappingAction, ставим точку остановки напротив строки заполнения элемента dataGrid1 (рис. 12.19):

 Точка остановки

Рис. 12.19. Точка остановки

Запускаем приложение. В любом месте кода щелкаем правой кнопкой мыши, в меню выбираем пункт "QuickWatch_". В появившемся окне вводим следующее выражение:

dsCustomers.Tables["Customers"].Columns

Нажимаем кнопку "Recalculate" (или просто клавишу Enter) - появляется группа, содержащая коллекцию Columns таблицы Customers объекта dsCustomers (рис. 12.20):

 Окно QuickWatch. Коллекция Columns

Рис. 12.20. Окно QuickWatch. Коллекция Columns

Прокручиваем список, выбираем "List", затем [0]. Мы видим название поля - "CustomerID" и значения параметров: " AllowDBNull5Как вы помните, свойство "AllowDBNull" объекта DataColumn определяет возможность пустых значений: DataColumn myColumn; DataColumn dcmyColumn = dtMyTable.Columns.Add("Название", typeof(Int32)); dcmyColumn.Unique = true; dcmyColumn.AllowDBNull = false; " - false, MaxLength - 5 (рис. 12.20a), что соответствует определению этого поля в таблице Customers самой базы данных (см. рис. 12.18).

 Поле "CustomerID" в окне QuickWatch при значении "AddWithKey" свойства "MissingSchemaAction"

Рис. 12.20a. Поле "CustomerID" в окне QuickWatch при значении "AddWithKey" свойства "MissingSchemaAction"

Таким образом, при значении AddWithKey свойства MissingSchema Action для описания добавляемого поля будут взяты значения параметров из базы данных. Закомментируем строку со значением AddWithKey, уберем комментарии со значения Add, запустим приложение и снова откроем окно QuickWatch. На этот раз в добавляемом столбце используются параметры, определенные при создании схемы, в частности, AllowDBNull и MaxLength (рис. 12.21):

 Поле CustomerID в окне QuickWatch при значении Add свойства MissingSchemaAction

увеличить изображение
Рис. 12.21. Поле CustomerID в окне QuickWatch при значении Add свойства MissingSchemaAction

Можно заметить, что другие параметры, например AutoIncrement, Namespace, также остались без изменений.

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

Сделаем теперь такое же приложение программно. Создайте новый Windows-проект и назовите его "ProgrammMissingSchemaAction". Перетаскиваем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Подключаем пространство имен для работы с базой данных:

using System.Data.SqlClient;

В классе формы создаем строки commandText и connectionString:

string commandText = "SELECT * FROM Customers";
string connectionString = "workstation id=7EA2B2F6068D473;integrated
 security=SSPI;data sou" + "rce=\"(local)\";persist
 security info=False;initial catalog=Northwind";

В конструкторе формы создаем подключение к базе данных, а также одно поле - dсCustomerID:

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 dsCustomers = new DataSet();
	DataTable dtCustomers =
	 dsCustomers.Tables.Add("Customers");
	DataColumn dсCustomerID =
	 dtCustomers.Columns.Add("CustomerID", typeof(string));
	dсCustomerID.Unique = true;
	dataAdapter.MissingSchemaAction = MissingSchemaAction.Add;
	//dataAdapter.MissingSchemaAction = MissingSchemaAction.Ignore;
	//dataAdapter.MissingSchemaAction = MissingSchemaAction.Error;
	//dataAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
	dataAdapter.Fill(dsCustomers, "Customers");
	dataGrid1.DataSource = dsCustomers;
}

Перебирая различные значения свойства MissingSchemaAction, получаем результаты, совпадающие с аналогичными значениями приложения VisualMissingMappingAction.

Обратим здесь внимание на важность задаваемых названий. Правильный фрагмент кода имеет следующий вид:

...
DataTable dtCustomers = dsCustomers.Tables.Add("Customers");
...
dataAdapter.Fill(dsCustomers, "Customers");
...

Не будем указывать название таблицы при добавлении объекта dtCustomers в DataSet:

...
DataTable dtCustomers = dsCustomers.Tables.Add();
...
dataAdapter.Fill(dsCustomers, "Customers");
...

Запускаем приложение (при значении "Add" свойства Missing SchemaAction). Объект DataSet содержит теперь две таблицы - Table1 с программно определенной схемой и Customers с данными, извлеченными из базы (рис. 12.22):

 Две таблицы в объекте  DataSet - "Table1" и "Customers"

Рис. 12.22. Две таблицы в объекте DataSet - "Table1" и "Customers"

Подобный результат получаем, не указывая в методе Fill, какую таблицу заполнять:

...
DataTable dtCustomers = dsCustomers.Tables.Add();
...
dataAdapter.Fill(dsCustomers, "Customers");
...

Запускаем приложение. Таблица Customers соответствует программно определенной схеме, а Table - таблице базы данных (рис. 12.23):

 Две таблицы в объекте DataSet - Customers и Table

Рис. 12.23. Две таблицы в объекте DataSet - Customers и Table

При определении источника данных для объекта DataGrid в результате можно легко сделать ошибку, например, следующий фрагмент кода устанавливает значение Ignore свойства MissingSchemaAction, но в результате его выполнения просто выводится структура объекта DataSet (рис. 12.24):

...
DataTable dtCustomers =
 dsCustomers.Tables.Add("Customers");
DataColumn dсCustomerID =
 dtCustomers.Columns.Add("CustomerID", typeof(string));
dсCustomerID.Unique = true;
dataAdapter.MissingSchemaAction = MissingSchemaAction.Ignore;
dataAdapter.Fill(dsCustomers);
dataGrid1.DataSource =
 dsCustomers.Tables["Customers"].DefaultView;
}
 Вывод структуры объекта DataSet

Рис. 12.24. Вывод структуры объекта DataSet

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

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