0

我可以通过尝试在一个相同的连接中打开 2 个连接来成功重现这一点TransactionScope(即使第一个连接在打开下一个连接之前也已关闭),如下所示:

 var connectionString = "some connection";
 using (var t = new TransactionScope())
 {
    using (var con1 = new OracleConnection(connectionString))
    {
       con1.Open();
    }                    
    using (var con2 = new OracleConnection(connectionString))
    {
       con2.Open();//exception thrown at here
    }
 }  

实际上,我正在尝试利用为我的存储库TransactionScope实现某种类型的Ambient transaction存储库(每个存储库都使用一个相同的连接字符串打开自己的连接)。上面的代码尽可能地简化以帮助重现异常。

TransactionScope我不太确定我做错了什么或者OracleManagedDataAccess至少在.NET Standard. 我的项目针对 .NET Standard 2.0 (lib) 和 .NET Core (app) 2.2,OracleManagedDataAccess通过 nuget 安装(当然针对 .NET Standard)并且版本为2.19.3.

这是上面发布的异常的堆栈跟踪:

在 OracleInternal.MTS.MTSRMManager.CCPEnlistTransaction(OracleConnectionImpl connImpl, Transaction transaction, MTSTxnRM txnRM.PoolManager`OracleInBranchConnectionPx) 上的 OracleInternal.MTS.MTSRMManager.CCPEnlistDistributedTxnToSysTxn(OracleConnectionImpl connImpl, Transaction txn, MTSTxnRM txnRM, MTSTxnBranch
txnBranch
) .GetEnlisted(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, OracleConnection connRefForCriteria)
在 OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securePassword, SecureString secureProxyPassword, OracleConnection connRefForCriteria)
在 Oracle.ManagedDataAccess.Client.OracleConnection。打开()

我有一种感觉,这是一个非常棘手的问题,几乎取决于OracleManagedDataAccess. 如果我不能使用TransactionScope,将没有简单的方法来实现Ambient transaction

4

1 回答 1

1

TransactionScope内的单个连接应按预期工作。当您登记到TransactionScope的两个连接时,您正在尝试执行分布式事务,这在 .NET Core 中不受支持:

从 2.1 版开始,.NET Core 中的 System.Transactions 实现不包括对分布式事务的支持,因此您不能使用 TransactionScope 或 CommittableTransaction 来协调多个资源管理器之间的事务。

(来自 Microsoft Docs 关于 EF Core Using Transactions的文章)。

不支持分布式事务的理由是它们依赖于特定于 Windows 的MSDTC。它与作为跨平台框架的 .NET Core 路线图不太一致。

编辑:另一种方法

一般来说,在决定依赖分布式事务时应该格外小心,因为这些事务很容易成为可伸缩性的瓶颈。在现代架构中,通常不鼓励分布式事务。

在您的情况下,由于您的所有资源都是与同一数据库的连接,因此您实际上并不需要分布式事务。我建议实施(环境)工作单元

例如,您的应用程序中的每个逻辑/业务操作可能都有一个工作单元实例。工作单元实例将缓冲所有请求的对数据库的修改(使用您自己的数据结构来表示修改)。在操作结束时,将提交工作单元。提交操作将包括:

  • 打开数据库连接和数据库事务
  • 使用单个 DB 连接执行所有缓冲修改
  • 提交数据库事务并关闭数据库连接

作为另一个示例,Entity Framework Core 在DBContext类中实现了工作单元模式。

于 2019-06-16T17:37:31.980 回答