我们有一个在事务范围内运行的测试。我们在最后处理事务范围以避免更改数据库。
这在大多数情况下都可以正常工作。
但是,当我们使用实体框架执行包含事务的存储过程时,该事务在存储过程中提交。我们收到以下错误:
"分布式事务已完成。在新事务或 NULL 事务中登记此会话。\r\n "
是否可以将事务范围与在存储过程中提交事务结合起来?
我们有一个在事务范围内运行的测试。我们在最后处理事务范围以避免更改数据库。
这在大多数情况下都可以正常工作。
但是,当我们使用实体框架执行包含事务的存储过程时,该事务在存储过程中提交。我们收到以下错误:
"分布式事务已完成。在新事务或 NULL 事务中登记此会话。\r\n "
是否可以将事务范围与在存储过程中提交事务结合起来?
虽然您可能会也可能无法解决这个特定问题,但我建议完全避免它可能是一个更好的选择。如您所见,依靠事务来保证您的数据库处于特定状态并不总是有效。此外,因为您使用到数据库的多个连接,所以您已经自动将发生的任何事务提升为分布式事务——这可能是一个微妙的区别,但它改变了测试的性质。您最终可能会编写代码来克服分布式事务的特殊限制,否则这些限制是不需要的。
更好的策略是——无论如何,对于单元测试——模拟数据库依赖,使用内存模拟或假对象代替数据库。我已经为 LINQ to SQL 做了类似的事情(请参阅我关于该主题的博客条目)对于集成测试,我认为您最好使用测试实例并编写设置代码,将数据库的状态重新初始化为每个之前的已知值测试而不是引入额外的事务来清理事情。这样,如果您的清理代码在测试中失败,它不会影响正在运行的其他测试。
我在 SP 中使用以下代码来处理事务当前可能生效或未生效的上下文:-
DECLARE @InTran int
Set @InTran = @@TRANCOUNT
IF @InTran = 0 BEGIN TRANSACTION
/* Stuff happens */
IF @InTran = 0 AND @@TRANCOUNT > 0 COMMIT TRANSACTION
我唯一不确定的是@@TRANCOUNT 是否反映了来自 Transaction 范围的事务,但它值得一试。