将 TransactionScope 与 OracleManagedDataAccess 一起使用,抛出 System.PlatformNotSupportedException:“此平台不支持操作。”

问题描述 投票:0回答:2

我可以通过尝试在同一个连接中打开 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
。 我的项目面向 .NET Standard 2.0 (lib) 和 .NET Core (app) 2.2,
OracleManagedDataAccess
是通过 nuget 安装的(当然是针对 .NET Standard)并且版本为
.NET Standard

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

在 OracleInternal.MTS.MTSRMManager.CCPEnlistDistributedTxnToSysTxn(OracleConnectionImpl connImpl,事务 txn,MTSTxnRM txnRM,MTSTxnBranch txnBranch)

在OracleInternal.MTS.MTSRMManager.CCPEnlistTransaction(OracleConnectionImpl connImpl,事务事务,MTSTxnRM txnRM,MTSTxnBranch txnBranch)

在 OracleInternal.ConnectionPool.PoolManager`3.GetEnlisted(ConnectionString csWithDiffOrNewPwd,布尔值 bGetForApp,OracleConnection connRefForCriteria)
在 OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securePassword, SecureString secureProxyPassword, OracleConnection connRefForCriteria)

在 Oracle.ManagedDataAccess.Client.OracleConnection.Open()


我有一种感觉,这是一个非常棘手的问题,几乎取决于
OracleManagedDataAccess

。如果我不能使用
2.19.3

,就没有简单的方法来实现

OracleManagedDataAccess
    
TransactionScope

内的单个连接应该按预期工作。 当您登记到
c# oracle transactions transactionscope oracle-manageddataaccess
2个回答
3
投票
的两个连接时,您正在尝试执行分布式事务,这在 .NET Core 中不受支持:

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

(来自有关 EF Core
使用事务

的 Microsoft Docs 文章)。

不支持分布式事务的理由是它们依赖于

MSDTC,这是特定于Windows的。它与 .NET Core 作为跨平台框架的路线图不太相符。

编辑:另一种方法

一般来说,应该格外谨慎地做出依赖分布式事务的决定,因为这些事务很容易成为可扩展性瓶颈。在现代架构中,通常不鼓励分布式事务。

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

工作单元

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

打开数据库连接和数据库事务

使用单个数据库连接执行所有缓冲修改

    提交数据库事务并关闭数据库连接
  • 另一个例子,Entity Framework Core 在
  • DBContext
  • 类中实现工作单元模式。

我设法通过抑制是否存在现有交易并且仍然存在来解决 设置 TransactionScopeAsyncFlowOption.Enabled 并且它工作完美

TransactionScope

0
投票

© www.soinside.com 2019 - 2024. All rights reserved.