Генерирование 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.