Генерирование SQL-команд с помощью типов построителя команд

Генерирование SQL-команд с помощью типов построителя команд

Вы должны согласиться с тем, что для работы с адаптерами данных может потребоваться ввод довольно большого объема программного кода, а также создание всех четырех объектов команд и соответствующей строки соединения (или DbConnection-объекта). Чтобы упростить дело, в .NET 2.0 каждый из поставщиков данных ADO.NET предлагает тип построителя команд. Используя этот тип, вы можете автоматически получать объекты команд, содержащие правильные типы команд Insert, Delete и Update на базе исходного оператора Select.

Тип SqlCommandBuilder автоматически генерирует значения для свойств InsertCommand, UpdateCommand и DeleteCommand объекта SqlDataAdapter на основе значения SelectCommand. Очевидным преимуществом здесь является то, что исключается необходимость строить все типы SqlCommand и SqlParameter вручную.

Здесь возникает вопрос о том, как построитель команд может строить указанные объекты SQL-команд "на лету". Оказывается, все дело в метаданных. В среде выполнения, когда вы вызываете метод Update() адаптера данных, соответствующий построитель команд читает данные структуры базы данных для автоматического генерирования объектов соответствующих команд вставки, удаления и обновления данных.

Рассмотрите следующий пример, в котором строка из DataSet удаляется с помощью автоматически сгенерированных SQL-операторов. Кроме того, для каждого объекта команды соответствующая команда выводится на печать.

static void Main(string[] args) {

 DataSet theCarsInventory = new DataSet();

 // Создание соединения.

 SqlConnection cn = new SqlConnection("server=(local);User ID=sa;Pwd=;database=Cars");

 // Автоматическое генерирование команд Insert, Update и Delete

 // на основе существующей команды Select.

 SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Inventory", cn);

 SqlCommandBuilder invBuilder = new SqlCommandBuilder(da);

 // Заполнение DataSet.

 da.Fill(theCarsInventory, "Inventory");

 PrintDataSet(theCarsInventory);

 // Удаление строки на основании пользовательского ввода

 // и обновление базы данных.

 try {

  Console.Write("Номер строки для удаления: ");

  int rowToDelete = int.Parse(Console.ReadLine());

  theCarsInventory.Tables["Inventory"].Rows[rowToDelete].Delete();

  da.Update(theCarsInventory, "Inventory");

 } catch (Exception e) {

  Console.WriteLine(e.Message);

 }

 // Новое заполнение и печать таблицы Inventory.

 theCarsInventory = new DataSet();

 da.Fill(theCarsInventory, "Inventory");

 PrintDataSet(theCarsInventory);

}

В этим фрагменте программного кода обратите внимание на то, что здесь объект построителя команд (в данном случае это SqlCommandBuilder) передается объекту адаптера данных в виде параметра конструктора и больше никак не используется. Как бы странно это ни выглядело, но это все, что вам требуется сделать (в минимальных условиях). Указанный тип в фоновом режиме сконфигурирует для адаптера данных остальные объекты команд.

Хотя идея получить кое-что, не предлагая ничего взамен, понравится многим, важно понять, что построители команд имеют некоторые (весьма важные) ограничения. В частности, построитель команд может автоматически генерировать SQL-команды для адаптера данных только в том случае, когда выполнены все следующие условия.

• Соответствующая команда Select взаимодействует только с одной таблицей (так что, например, соединения таблиц не допускаются).

• Для этой единственной таблицы назначен первичный ключ.

• Столбцы, представляющие первичный ключ, присутствуют в данном SQL-операторе Select.

Так или иначе, рис. 22.19 демонстрирует, что указанная строка удаляется из физической базы данных (при анализе программного кода этого примера следует различать значение CarID и порядковый номер строки).

Рис. 22.19. Использование автоматически генерируемых команд SQL

Исходный код. Проект MySqlCommandBuilder размещен в подкаталоге, соответствующем главе 22.