是否可以将事务范围与在存储过程内提交事务结合起来?
我们有一个在事务范围内运行的测试。我们在最后处理事务范围以避免更改数据库。
这在大多数情况下都可以正常工作。
但是,当我们使用实体框架执行包含事务的存储过程时,该事务是在存储过程内提交的。我们收到以下错误:
“分布式事务已完成。要么在新事务中登记此会话,要么在 NULL 事务中登记此会话。\r\n”
是否可以将事务范围与在存储过程内提交事务结合起来?
We have a test that runs within a transaction scope. We dispose of the transaction scope at the end to avoid changing the database.
This works fine in most cases.
However, when we use Entity Framework to execute a stored procedure which contains a transaction, which is committed inside the stored procedure. We get the following error:
"Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.\r\n "
Is it possible combine transaction scope with committing a transaction inside a stored procedure?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
虽然您可能无法解决这个特定问题,但我建议完全避免它可能是更好的选择。正如您所看到的,依靠事务来保证数据库处于特定状态并不总是有效。另外,因为您使用多个数据库连接,所以您已经自动将发生的任何事务提升为分布式事务——这也许是一个微妙的区别,但它改变了测试的性质。您最终可能会编写代码来克服分布式事务的特定限制,否则就不需要这些限制。
无论如何,对于单元测试来说,更好的策略是模拟数据库依赖关系,使用内存中的模拟或伪造对象代替数据库。我已经为 LINQ to SQL 做了类似的事情(请参阅我的 关于该主题的博客条目)对于集成测试,我认为您最好使用测试实例并编写设置代码,在每次测试之前将数据库的状态重新初始化为已知值引入额外的事务来清理问题。这样,如果您的清理代码在测试中失败,也不会影响正在运行的其他测试。
While you may or may not be able to solve this particular problem, I'd suggest that avoiding it entirely might be a better option. As you've seen, depending on a transaction to guarantee that your database is in a particular state doesn't always work. Also, because you are using multiple connections to the DB, you've automatically promoted any transactions that do occur to distributed transactions -- a subtle distinction, perhaps, but it changes the nature of the test. You may end up writing code to overcome the particular limitations of distributed transactions that wouldn't otherwise have been needed.
A better strategy would be -- for unit tests, anyway -- to mock out the database dependency, using in-memory mock or fake objects in place of the database. I've done something similar for LINQ to SQL (see my blog entry on the subject) For integration tests, I think you are better off using a test instance and writing set up code that reinitializes the state of the DB to known values before each test than introducing an extra transaction to clean things up. That way if your clean up code fails in a test, it won't affect other tests being run.
我在 SP 中使用以下代码来处理事务当前可能有效或无效的上下文:-
我唯一不确定的是 @@TRANCOUNT 是否反映了事务范围中的事务,但值得一试。
I use the following code inside an SP to handle contexts where a transaction may or may not be currently in force:-
Only thing I'm not sure of is if @@TRANCOUNT reflects a transaction from a Transaction scope, its worth a shot though.