【问题标题】:Is it possible combine transaction scope with committing a transaction inside a stored procedure?是否可以将事务范围与在存储过程中提交事务结合起来?
【发布时间】:2009-09-23 11:54:52
【问题描述】:
我们有一个在事务范围内运行的测试。我们在最后处理事务范围以避免更改数据库。
这在大多数情况下都可以正常工作。
但是,当我们使用 Entity Framework 执行包含事务的存储过程时,该事务在存储过程中提交。我们得到以下错误:
“分布式事务已完成。将此会话加入新事务或 NULL 事务。\r\n”
是否可以将事务范围与在存储过程中提交事务结合起来?
【问题讨论】:
标签:
c#
sql-server
entity-framework
transactions
transactionscope
【解决方案1】:
虽然您可能无法解决这个特定问题,但我建议完全避免它可能是一个更好的选择。如您所见,依靠事务来保证您的数据库处于特定状态并不总是有效。此外,因为您使用到数据库的多个连接,所以您已经自动将发生的任何事务提升为分布式事务——这可能是一个微妙的区别,但它改变了测试的性质。您最终可能会编写代码来克服分布式事务的特殊限制,否则这些限制是不需要的。
更好的策略是——无论如何,对于单元测试——模拟数据库依赖,使用内存模拟或假对象代替数据库。我已经为 LINQ to SQL 做了类似的事情(请参阅我的 blog entry 主题)对于集成测试,我认为您最好使用测试实例并编写将数据库状态重新初始化为已知值的设置代码每个测试都比引入额外的事务来清理事情。这样,如果您的清理代码在测试中失败,它不会影响正在运行的其他测试。
【解决方案2】:
我在 SP 中使用以下代码来处理事务当前可能生效或未生效的上下文:-
DECLARE @InTran int
Set @InTran = @@TRANCOUNT
IF @InTran = 0 BEGIN TRANSACTION
/* Stuff happens */
IF @InTran = 0 AND @@TRANCOUNT > 0 COMMIT TRANSACTION
我唯一不确定的是@@TRANCOUNT 是否反映了来自 Transaction 范围的事务,但值得一试。