Транзакции и обновление базы данных
Когда преобразователь данных обновляет содержимое базы данных, это не делается одной транзакцией. Если необходимо, чтобы несколько операций выполнялись за одну транзакцию, в программе следует предусмотреть управление транзакциями.
Объект SqlConnection содержит метод BeginTransaction, возвращающий объект SqlTransaction. При вызове метода BeginTransaction следует определить уровень локализации (выполняемых операций). Когда вы точно знаете, что делаете, и понимаете внутреннюю суть вещей, вы можете повысить производительность и масштабируемость приложения установкой соответствующего уровня локализации (выполняемых операций). Если установить уровень локализации (выполняемых операций) некорректно или даже просто неподходящим образом, это может привести к некорректности или несогласованности полученных данных.
Для выполнения или отмены транзакции в классе имеются методы Commit (Фиксировать) и Rollback (Откат). Вы открываете SqlConnection, вызываете метод BeginTransaction, используете SqlDataAdapter как обычно, а затем вызываете SqlTransaction::Commit (Фиксировать) или SqlTransaction::Rollback (Откат), в зависимости от необходимости. Затем закрываете соединение. Для установки точки сохранения (save point) транзакции используется метод Save (Сохранить).
В целях минимизации используемых ресурсов, а, следовательно, для повышения масштабируемости вашего приложения, может оказаться желательным минимизировать промежуток времени между вызовами методов BeginTransaction и Commit (Фиксировать) или Rollback (Откат).
Приведем фрагмент кода из примера Transaction. В нем используется база данных AirlineBroker, описанная в предыдущей главе. Для иллюстрации здесь используется объект SqlCommandBuilder, рассмотренный выше.
conn = new SqlConnection(ConnString); conn › Open(); // Открыть trans = conn › BeginTransaction(); da = new SqlDataAdapter; ds = new DataSet; // новый Набор данных da › SelectCommand = new SqlCommand(and, conn, trans); SqlCommandBuilder *sb = new SqlCommandBuilder(da); da › Fill(ds, "Airlines"); // Авиалинии DataRow *newRow = ds › Tables › get_Item("Airlines") › NewRow(); // Авиалинии newRow › set_Item("Name", S"Midway"); // Название, "На полпути" newRow › set_Item("Abbreviation", S"M"); // Сокращение newRow › set_Item("WebSite", S"www.midway.com"); // Web-узел newRow › set_Item("ReservationNumber", S"555-555-1212"); ds › Tables › get_Item("Airlines") › Rows › Add(newRow); // Авиалинии Console::WriteLine( sb › GetInsertCommand() › CommandText); Console::WriteLine ( sb › GetDeleteCommand() › CommandText); Console::WriteLine( sb › GetUpdateCommand() › CommandText); pEnum = sb › GetInsertCommand() › Parameters › GetEnumerator(); // Параметры while (pEnum › MoveNext()) { SqlParameter *p = dynamic_cast<SqlParameter *>(pEnum › Current); Console::WriteLine ( "{0, -10} {I, -10}", p › ParameterName, p › SourceColumn); } da › Update(ds, "Airlines"); // Авиалинии trans › Commit(); trans = 0; conn › Close ();
Для полной уверенности в корректности работы источника данных SQL Server следует использовать методы Commit (Фиксировать) и Rollback (Откат) объекта SqlTransaction для подтверждения или отмены транзакции, выполнение которой начато вызовом метода SqlConnection::BeginTransaction. При этом не стоит использовать операторы транзакций SQL Server.
Если вы в своей работе с базой данных используете хранимые процедуры, вы можете, конечно, использовать операторы транзакций SQL Server внутри хранимых процедур вместо объекта SqlTransaction. Хранимые процедуры могут инкапсулировать изменения, произведенные в результате транзакций. Это делает, в частности, хранимая процедура MakeReservation базы данных HotelBroker (Посредник, бронирующий места в гостинице).