using (Transactions.TransactionScope tx = new Transactions.TransactionScope()) {
using (SqlConnection conn = new SqlConnection(CONNECTIONSTRING)) {
conn.Open();
var cmd = new SqlCommand("Update Officer1s Set isLocked='Y' where a='b'", conn); //refer to an nonexsiting name on purpose.
var transaction = conn.BeginTransaction();
cmd.Transaction = transaction;
try {
var a = cmd.ExecuteNonQuery();
} catch (Exception ex) {
transaction.Rollback();//Invalid object name 'Officer1s'.
}
using (SqlConnection conn2 = new SqlConnection(CONNECTIONSTRING)) {
conn2.Open(); //throw exception
}
}
}
在我的实际应用程序中,入口方法被TransactionScope包围。 entry方法调用了很多方法并且非常深入。如果在任何连接中sql抛出任何SqlException(为了演示,我故意引用一个非兴奋的名称)并回滚内部事务,然后我无法打开第二个连接,因为将抛出异常说"事务已经。中止"
为什么外部交易中止?是否支持这种用法?
我正在使用SQL Server 2014。
答案 0 :(得分:0)
您获得的具体行为可能取决于各种因素,例如您是否使用事务池。但是,一般而言,这不是交易的工作方式。
连接很昂贵,所以你想要打开一个连接并一遍又一遍地使用它。连接中存在事务,因此在另一个连接上使用相同的事务对象无效。
根据样本判断,代码看起来并不像是使用嵌套事务,而是使用嵌套连接",这不是正确的方法。应该发生的是:
如果需要,可以在SQL Server Mgmt Studio中打开两个查询会话。在第一个中,执行BEGIN TRAN,然后在表中插入一行。现在,在不执行COMMIT的情况下,切换到另一个会话并查询该表。你不会看到刚刚添加的行(除非你的ISOLATION LEVEL 脏读;我希望不会这样)。这是事务的隔离属性。
上述代码中应该发生的是,当捕获到异常并且事务回滚时,事务对象完成。下一个逻辑工作单元以新的BeginTransaction()开始。