#c# #transactions
#c# #транзакции
Вопрос:
До сих пор я использую два блока 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{}
}
}
}
Имеют ли они оба одинаковый результат? Какой из двух более предпочтителен?
Комментарии:
1. Если
connection.Open();
throws , то это бесполезноtransaction.Rollback
, и он будет выдавать aNullReferenceException
(который будет перехвачен вторымtry...catch
).2. @xanatos в каком случае? … во-первых, open находится вне catch «отката», а во-вторых, есть защита
3. Ни то, ни другое не является предпочтительным, ваш код слишком многословен, даже если вы настаиваете на использовании явных транзакций.
TransactionScope
Сначала посмотрите вверх. ЯвноеTransaction.Rollback()
почти никогда не требуется в любом случае, потому что откат происходит автоматически, если.Commit()
он не был вызван к моменту удаления транзакции (что вы должны делать вusing
блоке).4. @Selvin В первом, тот, который делает
transaction.Rollback()
доверие, котороеtransaction
есть!= null
… Я даже видел (эквивалент второго)transaction?.Rollback()
… Но предложения Джеруна намного лучше.using
везде, где вы можете, это ключ к исправлению. Сетевое программирование5. доверие к этой транзакции равно != null , потому что оно не будет null …
connection.BeginTransaction
возвращает ненулевую транзакцию или выдает … но если throws тогда выполнение завершится внешним пустым catch и никогда не выполнит откат … та же история, когдаconnection.Open
бросит
Ответ №1:
Ни один из этих двух методов не подходит. Они слишком подробны.
Лучший метод — просто поместить 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
что все очистится.
Если вам нужно перехватить, чтобы отобразить сообщение пользователю, сделайте это вне кода, т. Е. Поместите a try/catch
вокруг всего этого. Не выполняйте код очистки самостоятельно
Комментарии:
1. И где я должен разместить try and catch? перед открытием соединения?
2. Ты не
try
должен илиcatch
что-то в этом роде.using
справлюсь со всем этим.3. Что, если возникнет исключение?
4.
using
все будет очищено. Если вам нужно перехватить, чтобы отобразить сообщение пользователю, сделайте это вне кода, т. Е. Поместите atry/catch
вокруг всего этого. Не выполняйте код очистки самостоятельно5. Это бессмысленно. Вам нужно поместить try и catch для выполнения отката, если что-то пойдет не так. транзакция. Откат (). За исключением случаев, когда мне не нужен откат в using statement