Zol*_*yak 5 c# msdtc entity-framework transactions distributed-transactions
在我的代码中有要处理的事务:
using (var scope = new TransactionScope())
{
repo1.SaveSomething();
repo2.SaveAnythingElse();
scope.Complete();
}
Run Code Online (Sandbox Code Playgroud)
在 repo1 和 repo2 函数内部使用 using 创建自己的数据库上下文,并处理它们,事务就像一个魅力。
现在我添加另一个这样的代码,它开始丢弃一个异常:
底层提供程序在 Open 上失败。(EntityFramework) 分布式事务管理器 (MSDTC) 的网络访问已被禁用。请使用组件服务管理工具在 MSDTC 的安全配置中为网络访问启用 DTC。(System.Transactions) 事务管理器已禁用对远程/网络事务的支持。
我读到当连接在事务内部打开时,尽管具有相同的 sql server 相同的 db - 它需要 MSDTC 组件来处理它。我将代码更改为以下内容:
using (var scope = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
{
....
scope.Complete();
}
Run Code Online (Sandbox Code Playgroud)
现在异常消失了。
我的问题:
我认为简单的问题:) 任何帮助将不胜感激!
1)您绝对应该在默认的 Serializable 上为您的 TransactionScope 使用 ReadCommitted,但这与您的问题无关,请参见此处。
2) 当您有一个活动的 TransactionScope 时,任何时候您打开一个 SqlConnection 它将被登记在该事务中。如果没有其他资源参与事务,SqlClient 将开始本地或“轻量级”事务。这并没有涉及MSTDC; 它只是在打开的 SqlConnection 上启动的普通 SQL Server 事务。
如果关闭该 SqlConnection(或处理包含它的 EF DbContext),则连接将返回到连接池。但是它与其他池连接隔离,并且只是挂起直到事务完成或回滚。
如果您在同一个 TransactionScope 中打开一个新的 SqlConnection,使用完全相同的 ConnectionString,连接池不会获取新连接,而是返回已经在事务中登记的现有连接。
如果您在同一个 TransactionScope 中使用不同的 ConnectionString 打开一个新的 SqlConnection,或者当连接池中没有已经登记在事务中的连接时,那么您将获得一个新的 SqlConnection,它将被登记在事务中。但是由于事务中已经有另一个 SqlConnection,这将需要 MSTDC 创建一个真正的分布式事务。这称为“促销”;您的“轻量级交易”被“提升”为“分布式交易”。
因此,在此背景下,审核您的连接生命周期和 ConnectionString 使用情况,以了解您在此处触发促销的原因。
换句话说,通过正确的 ConnectionString 使用和连接生命周期管理,您应该能够运行以下代码:
using (var scope = new TransactionScope())
{
repo1.SaveSomething();
repo2.SaveAnythingElse();
scope.Complete();
}
Run Code Online (Sandbox Code Playgroud)
不触发分布式事务。
| 归档时间: |
|
| 查看次数: |
2876 次 |
| 最近记录: |