将 TransactionScope 与 OracleManagedDataAccess 抛出系统一起使用。PlatformNotSupportedException:"此平台不支持操作。



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

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中不受OracleManagedDataAccess支持. 我的项目面向.NET Standard 2.0(lib)和.NET Core(应用程序)2.2,OracleManagedDataAccess是通过nuget安装的(当然是针对.NET Standard)并且版本2.19.3

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

at OracleInternal.MTS.MTSRMManager.CCPEnlistDistributedTxnToSysTxn(OracleConnectionImpl connImpl, Transaction txn, MTSTxnRM txnRM, MTSTxnBranch txnBranch)at

OracleInternal.MTS.MTSRMManager.CCPEnlistTransaction(
OracleConnectionImpl connImpl, Transaction transaction, MTSTxnRM txnRM, MTSTxnBranch txnBranch)
at OracleInternal.ConnectionPool.PoolManager'3.GetEnlisted(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, OracleConnectionconnRefForCriteria)at OracleInternal.ConnectionPool.OracleConnectionDispenser'3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword, OracleConnection connRefForCriteria)at Oracle.ManagedDataAccess.Client.OracleConnection.Open()

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

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

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

(摘自Microsoft Docs 文章中有关使用事务的 EF Core 的文章)。

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

编辑:另一种方法

通常,在做出依赖分布式事务的决定时应格外谨慎,因为这些事务很容易成为可伸缩性瓶颈。在现代体系结构中,通常不鼓励分布式事务。

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

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

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

作为另一个示例,实体框架核心在 DBContext 类中实现了工作单元模式。

相关内容

  • 没有找到相关文章

最新更新