Самый чистый способ использовать BeginTransaction с помощью try catch
До сих пор я использую два блока try catch для своих запросов. Первый вызовет ошибку, если соединение не будет установлено. Второй проверяет, SqlCommand
успешно ли выполнено. Как в примере ниже
try
{
using(varconnection=newSqlConnection())
using(varcmd=newSqlCommand())
{
connection.Open();
var transaction=connection.BeginTransaction();
cmd.Connection=connection;
cmd.Transaction=transaction;
try
{
cmd.CommandText="InsertintoCustomers(Name)values('Dimitri')";
cmd.ExecuteNonQuery();
cmd.CommandText="InsertintoCustomers(Name)values('George')";
cmd.ExecuteNonQuery();
transaction.Commit();
}
catch
{
try{transaction.Rollback();}catch{}
}
}
}
catch
{
}
Я нашел второй пример, который мне кажется более понятным.
SqlTransactiontransaction=null;
using(varconnection=newSqlConnection())
using(varcmd=newSqlCommand())
{
try
{
connection.Open();
transaction=connection.BeginTransaction();
cmd.Connection=connection;
cmd.Transaction=transaction;
cmd.CommandText="InsertintoCustomers(Name)values('Dimitri')";
cmd.ExecuteNonQuery();
cmd.CommandText="InsertintoCustomers(Name)values('George')";
cmd.ExecuteNonQuery();
transaction.Commit();
transaction.Dispose();
transaction=null;
}
catch
{
if(transaction!=null)
{
try{transaction.Rollback();}catch{}
}
}
}
У них обоих одинаковый результат? Что из двух предпочтительнее?
Ответы
Ни один из этих двух методов не годится. Они слишком многословны.
Лучший способ - просто поместить Transaction
в a using
, также мы должны использовать параметр для запроса:
using(var connection = new SqlConnection(connString))
using(var cmd = new SqlCommand("Insert into Customers (Name) values (@Name));"))
{
var param = cmd.Parameters.Add("@Name", SqlDbType.VarChar, insert_column_length_here);
connection.Open();
using(var transaction = connection.BeginTransaction())
{
cmd.Transaction = transaction;
param.Value = "Dimitri";
cmd.ExecuteNonQuery();
param.Value = "George";
cmd.ExecuteNonQuery();
transaction.Commit();
}
}
Мы можем видеть, что при удалении объекта транзакции произойдет автоматический откат, если он еще не зафиксирован, просмотрев исходный код . Так using
что уберу все.
Если вам нужно поймать, чтобы отобразить сообщение пользователю, сделайте это вне кода, то есть поместите try/catch
вокруг всего этого. Не выполняйте код очистки самостоятельно