Как использовать транзакции с datacontext

Можно ли использовать транзакции с datacontext, чтобы я мог откатить состояние контекста после ошибки? И если да, то как это работает?

Ответы

Ответ 1

DataContext по умолчанию запускает внешнюю транзакцию, так что это просто вопрос обеспечения транзакции в области видимости. Детали становятся главной проблемой:

  • Какие параметры вам нужны (например, уровень изоляции)
  • Вы хотите новую транзакцию или повторно использовать существующую транзакцию (например, для операции аудита/ведения журнала может потребоваться новая транзакция, чтобы ее можно было совершить, даже если общая бизнес-операция завершилась неудачей и, следовательно, внешняя транзакция откат).

Это упрощает некоторый код прототипа, настоящий код использует помощники для создания транзакций с политическими параметрами (одной из целей прототипа было изучение влияния этих параметров).

using (var trans = new TransactionScope(
                           TransactionScopeOption.Required,
                           new TransactionOptions {
                               IsolationLevel = IsolationLevel.ReadCommitted
                           },
                           EnterpriseServicesInteropOption.Automatic)) {
    // Perform operations using your DC, including submitting changes

    if (allOK) {
        trans.Complete();
    }
}

Если Complete() не вызывается, транзакция будет отменена. Если есть область транзакции, содержащаяся в транзакции, то как внутренние, так и внешние транзакции должны быть заполнены для изменений в базе данных, которая должна быть зафиксирована.

Ответ 2

Я использую их в тестировании все время:)

try
{
  dc.Connection.Open();
  dc.Transaction = dc.Connection.BeginTransaction();

  dc.SubmitChanges();
}
finally
{
  dc.Transaction.Rollback();
}

UPDATE

Это будет ВСЕГДА откат после факта. Я использую это при тестировании.

Ответ 3

Что-то вроде этого, возможно:

try
{
    using (TransactionScope scope = new TransactionScope())
    {
        //Do some stuff

        //Submit changes, use ConflictMode to specify what to do
        context.SubmitChanges(ConflictMode.ContinueOnConflict);

        scope.Complete();
    }
}
catch (ChangeConflictException cce)
{
        //Exception, as the scope was not completed it will rollback
}

Ответ 4

Это не так просто, как метод TransactionScope, но, насколько я понимаю, это "правильный" способ сделать это для LINQ-to-SQL. Он не требует ссылки на System.Transactions.

dataContext.Connection.Open();
using (dataContext.Transaction = dataContext.Connection.BeginTransaction())
{
    dataContext.SubmitChanges();

    if (allOK)
    {
        dataContext.Transaction.Commit();
    }
    else
    {
        dataContext.Transaction.RollBack();
    }
}

Конечно, RollBack требуется только в том случае, если вы намерены выполнять дополнительные операции с данными в процессе использования, иначе изменения будут автоматически отменены.

Ответ 5

Что-то вроде этого:

using (YourDatacontext m_DB = new YourDatacontext())
using (TransactionScope tran = new TransactionScope())
{
   try
   {
      //make here the changes
      m_DB.SubmitChanges();
      tran.Complete();
   }
   catch (Exception ex)
   {
       Transaction.Current.Rollback();
   }
}