请考虑以下方法。
DoA()
{
using (TransactionScope scope = new TransactionScope)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand(query, connection);
command.ExecuteNonReader();
DoB();
scope.Complete();
}
}
}
DoB()
{
using (TransactionScope scope = new TransactionScope)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand(query, connection);
command.ExecuteNonReader();
DoC();
scope.Complete();
}
}
}
DoC()
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand(query, connection);
command.ExecuteNonReader();
}
}
如果我们致电DoA()
,那么DoB()
和DoC()
中的后续互动是否会在DoA()
的交易环境中运行,因为它与SQL Server有关? DoC()是否在DoA()
和DoB()
的交易中运行?
(或者我是否误解了某些事情?)
答案 0 :(得分:4)
逻辑上所有代码都是单个事务。嵌套作用域不一定会创建新事务(除非您使用RequiresNew),因此它将是单个事务。现在,每个范围必须投票才能完成事务,因此如果删除Complete
,则在第二个范围内,应该导致整个事务回滚。
DoC也将成为交易的一部分;环境事务将检测新连接并自动登记。
请阅读所有详细信息here,其中说明了注册环境事务的行为以及不同选项Requires
,RequiresNew
和Suppress
。
另请注意,如果您的连接不使用完全相同的连接字符串,则会自动将整个事务提升为分布式事务。需要注意的事项。
答案 1 :(得分:2)
根据Andy的评论编辑:
似乎在SQL服务器上会发生类似这样的事情:
BEGIN TRANSACTION A
-- do A's work
-- B does NOT create a new transaction
-- do B's work
-- do C's work
COMMIT TRANSACTION A
如果在new TransactionScope(TransactionScopeOption.RequiresNew)
中使用DoB()
,则会发生以下情况。
BEGIN TRANSACTION A
-- do A's work
BEING TRANSACTION B
-- do B's work
-- do C's work
COMMIT TRANSACTION B
COMMIT TRANSACTION A