Технология Microsoft ADO.NET

       

Свойство 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):


увеличить изображение
Рис. 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") - всего один, для вывода только одного поля из таблицы базы данных.


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

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

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

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


Рис. 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):


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

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

sqlDataAdapter1.MissingSchemaAction = MissingSchemaAction.Error;



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


Рис. 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):


Рис. 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):


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

Прокручиваем список, выбираем "List", затем [0]. Мы видим название поля - "CustomerID" и значения параметров: "AllowDBNull5)" - false, MaxLength - 5 (рис. 12.20a), что соответствует определению этого поля в таблице Customers самой базы данных (см.




рис. 12.18).


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

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


увеличить изображение
Рис. 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):


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

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

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

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


Рис. 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; }


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

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

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


Содержание раздела