Транзакции в .net - PullRequest
       42

Транзакции в .net

137 голосов
/ 22 октября 2008

Каковы лучшие практики для выполнения транзакций в C # .Net 2.0. Какие классы следует использовать? На какие подводные камни нужно обратить внимание и т. Д. Все, что фиксирует и откатывает вещи. Я только начинаю проект, в котором мне может потребоваться выполнить некоторые транзакции при вставке данных в БД. Любые ответы или ссылки даже на простые вещи о транзакциях приветствуются.

Ответы [ 5 ]

258 голосов
/ 22 октября 2008

Есть 2 основных вида транзакций; транзакции соединения и окружающие транзакции. Транзакция соединения (такая как SqlTransaction) напрямую связана с соединением db (например, SqlConnection), что означает, что вам нужно постоянно передавать соединение - ОК в некоторых случаях, но не позволяет «создавать / использовать / освобождать» использование, и не позволяет кросс-дБ работать. Пример (отформатированный для пробела):

using (IDbTransaction tran = conn.BeginTransaction()) {
    try {
        // your code
        tran.Commit();
    }  catch {
        tran.Rollback();
        throw;
    }
}

Не слишком грязно, но ограничено нашей связью "conn". Если мы хотим вызвать разные методы, нам нужно передать «conn».

Альтернатива - внешняя транзакция; новый объект в .NET 2.0, объект TransactionScope (System.Transactions.dll) позволяет использовать различные операции (подходящие поставщики автоматически подключаются к внешней транзакции). Это позволяет легко встраиваться в существующий (не транзакционный) код и общаться с несколькими поставщиками (хотя DTC будет участвовать, если вы говорите с более чем одним).

Например:

using(TransactionScope tran = new TransactionScope()) {
    CallAMethodThatDoesSomeWork();
    CallAMethodThatDoesSomeMoreWork();
    tran.Complete();
}

Обратите внимание, что эти два метода могут обрабатывать свои собственные соединения (открывать / использовать / закрывать / удалять), но они будут тихо становиться частью транзакции окружения, без необходимости что-либо передавать.

Если ваш код содержит ошибки, Dispose () будет вызван без Complete (), поэтому он будет откатан. Поддерживается ожидаемое вложение и т. Д., Хотя вы не можете откатить внутреннюю транзакцию, но завершить внешнюю транзакцию: если кто-то недоволен, транзакция отменяется.

Другое преимущество TransactionScope заключается в том, что он не привязан только к базам данных; любой провайдер, поддерживающий транзакции, может использовать его. WCF, например. Или даже существуют некоторые объектные модели, совместимые с TransactionScope (то есть .NET-классы с возможностью отката - возможно, проще, чем памятные вещи, хотя я никогда не использовал этот подход сам).

В целом, очень, очень полезный объект.

Некоторые оговорки:

  • В SQL Server 2000 TransactionScope немедленно перейдет в DTC; это исправлено в SQL Server 2005 и выше, он может использовать LTM (гораздо меньше накладных расходов) до тех пор, пока вы не поговорите с 2 источниками и т. д., когда он повышен до DTC.
  • Существует глюк , который означает, что вам может понадобиться настроить строку подключения
11 голосов
/ 05 ноября 2012
protected void Button1_Click(object sender, EventArgs e)
   {


       using (SqlConnection connection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database.mdf;Integrated Security=True;User Instance=True"))
       {
           connection1.Open();

           // Start a local transaction.
           SqlTransaction sqlTran = connection1.BeginTransaction();

           // Enlist a command in the current transaction.
           SqlCommand command = connection1.CreateCommand();
           command.Transaction = sqlTran;

           try
           {
               // Execute two separate commands.
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('a','b','c')";
               command.ExecuteNonQuery();
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('x','y','z')";
               command.ExecuteNonQuery();

               // Commit the transaction.
               sqlTran.Commit();
               Label3.Text = "Both records were written to database.";
           }
           catch (Exception ex)
           {
               // Handle the exception if the transaction fails to commit.
               Label4.Text = ex.Message;


               try
               {
                   // Attempt to roll back the transaction.
                   sqlTran.Rollback();
               }
               catch (Exception exRollback)
               {
                   // Throws an InvalidOperationException if the connection 
                   // is closed or the transaction has already been rolled 
                   // back on the server.
                   Label5.Text = exRollback.Message;

               }
           }
       }


   }
3 голосов
/ 22 октября 2008

Вы также можете заключить транзакцию в собственную хранимую процедуру и обрабатывать ее таким образом, вместо того чтобы выполнять транзакции в самом C #.

1 голос
/ 22 октября 2008

, если вам это нужно только для вещей, связанных с БД, некоторые OR Mappers (например, NHibernate) поддерживают трансактино из коробки по умолчанию.

0 голосов
/ 22 октября 2008

Это также зависит от того, что вам нужно. Для базовых транзакций SQL вы можете попробовать выполнить транзакции TSQL, используя в своем коде BEGIN TRANS и COMMIT TRANS. Это самый простой способ, но у него есть сложность, и вы должны быть осторожны, чтобы правильно зафиксировать (и выполнить откат).

Я бы использовал что-то вроде

SQLTransaction trans = null;
using(trans = new SqlTransaction)
{
    ...
    Do SQL stuff here passing my trans into my various SQL executers
    ...
    trans.Commit  // May not be quite right
}

Любая ошибка выведет вас прямо из using, и транзакция всегда будет фиксироваться или откатываться (в зависимости от того, что вы скажете) Самая большая проблема, с которой мы столкнулись, заключалась в том, чтобы она всегда была совершенной. Использование гарантирует, что объем транзакции ограничен.

...