Ger*_*old 6 c# entity-framework transactions transactionscope
我们正在逐步用实体框架(4.3.1)替换遗留数据访问代码.在某些情况下,我们无法避免在一个工作单元中使用两种数据访问方式.理想情况下,这应该在一个事务中完成.但是,旧代码使用在完成工作单元时SqlTransaction调用的s,Commit()并且EF管理自己的事务.
所以我们考虑将"旧"和"新"代码包装在一个TransactionScope.但是,TransactionScope即使TransactionScope未完成,也始终执行周围的Commit .此代码段说明了我的问题:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
未命中时仍会提交更新语句scope.Complete().
所以看起来,我不能TransactionScope用来强制旧数据访问代码和SaveChanges上下文在一个事务中执行.或者有没有办法推翻SqlTransaction.Commit语句?
我知道这里有关于TransactionScope和SqlTransaction的更多帖子,但他们都(正确地)说使用TransactionScope时不需要(也不推荐)使用SqlTransaction.但不使用SqlTransaction不是一个选项.我们有一个遗留框架,它提交自己的SqlTransactions并且没有api可以挂钩它的事务机制.
小智 8
当未触发scope.Complete()时,仍会提交更新语句.
不好了!!TransacationScope未被使用1.
仅当在TransactionScope 之后(或内部)打开Connection时,自动登记才有效.
把Open 里面的TransactionScope 应该解决这个问题(甚至与手动交易?)作为连接然后将[通常]在环境TS上下文自动征用.
可以将现有连接登记到环境事务范围中:connection.EnlistTransaction(Transaction.Current).
或者,可以从现有交易创建TS,例如new TransactionScope(transaction),这在这里可能有用或者可能没有帮助.
创建一个手动交易,如果完全没问题,但TS(在解决问题之后!)使处理交易更简单,更容易..至少在大多数情况下:)
快乐的编码!
1 TS未用于"更新声明".它仍然[可能]用于context.SaveChanges()打开一个新的连接,然后自动登记.
我上面提供了一些选项,虽然我不确定简单的"嵌套"事务.看到上下文中使用的(密封?)API可能会揭示有关限制/限制的更多见解.