Игнорировать 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, используемого в контексте, может раскрыть больше понимания относительно ограничений / ограничений.