Игнорировать SqlTransaction.Commit в TransactionScope

Мы находимся в процессе постепенной замены устаревшего кода доступа к данным структурой сущностей (4.3.1). В некоторых случаях мы не можем избежать использования обоих способов доступа к данным в одной единице работы. В идеале это должно быть сделано за одну транзакцию. Тем не менее, старый код использует SqlTransaction с этим звонком Commit() когда единица работы выполнена, и EF управляет своими собственными транзакциями.

Поэтому мы подумали об упаковке "старого" и "нового" кода в TransactionScope, Тем не менее, коммит в окружении TransactionScope всегда выполняется, даже если TransactionScope не завершено. Этот фрагмент кода иллюстрирует мою проблему:

using (var conn = new SqlConnection("connection string"))
{
  conn.Open();
  using (var scope = new TransactionScope())
  {
    using (var tr = conn.BeginTransaction())
    {
      using (var cmd = conn.CreateCommand())
      {
        cmd.Transaction = tr;
        cmd.CommandText = "some update statement";
        cmd.ExecuteNonQuery();
      }
      tr.Commit();
    }
    // In reality the code above is part of a legacy DAL, immutable.
    // (can't insert SaveChanges before tr.Commit).
    context.SaveChanges();
    if (<all ok>) // pseudo code for exception handling.
        scope.Complete(); 
  }
}

Оператор обновления все еще фиксируется, когда scope.Complete() не ударил.

Так что, похоже, я не могу использовать TransactionScope заставить старый код доступа к данным и SaveChanges из контекста выполнить в одной транзакции. Или есть способ отменить оператор SqlTransaction.Commit?

Я знаю, что здесь есть больше сообщений о TransactionScope и SqlTransaction, но все они (справедливо) говорят, что использование SqlTransaction не является необходимым (и не рекомендуется) при использовании TransactionScope. Но не использовать SqlTransaction здесь не вариант. У нас есть устаревшая структура, которая совершает свою собственную SqlTransaction и у него нет API, чтобы подключиться к его механизму транзакций.

1 ответ

Решение

Оператор обновления по-прежнему фиксируется, когда область действия. Не совершено нажатие.

О нет!! TransacationScope не используется 1.

Автоматическая регистрация работает, только если Соединение открыто после (или внутри) TransactionScope.

Ввод Open внутри TransactionScope следует исправить эту проблему (даже с ручной транзакцией?), поскольку затем Connection [обычно] автоматически включается в контекст окружающего TS.

Существующее соединение может быть включено в объем транзакции: connection.EnlistTransaction(Transaction.Current),

Альтернативно, TS может быть создан из существующей транзакции, например new TransactionScope(transaction), который может или не может быть полезным здесь.

Создание ручной транзакции, если она идеально, но TS (после того, как уловлены ошибки!) Упрощает и облегчает работу с транзакциями... по крайней мере, в большинстве случаев:)

Удачного кодирования!


1 TS не используется для "оператора обновления". Это все еще будет [вероятно] использоваться для context.SaveChanges() как это откроет новое соединение, которое затем автоматически зачисляется.

Я предоставил некоторые варианты выше, хотя я не уверен насчет простой "вложенной" транзакции. Видение (запечатанного?) API, используемого в контексте, может раскрыть больше понимания относительно ограничений / ограничений.

Другие вопросы по тегам