Используйте TransactionScope с OracleManagedDataAccess, выбрасывая System.PlatformNotSupportedException: «Операция не поддерживается на этой платформе». - PullRequest
0 голосов
/ 16 июня 2019

Я могу успешно воспроизвести это, попробовав открыть 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 (приложение) 2.2, OracleManagedDataAccess устанавливается через nuget (конечно, нацеленный на .NET Standard) и имеет версию 2.19.3.

Вот трассировка стеков вышедшего выше исключения:

в 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 securedPassword, SecureString securedProxyPassword, OracleConnection connRefForCriteria)
в Oracle.ManagedDataAccess.Client.OracleConnection.Open ()

У меня такое ощущение, что это очень сложная проблема, зависящая почти от OracleManagedDataAccess. Если я не могу использовать TransactionScope, не будет простого способа реализовать Ambient transaction.

1 Ответ

1 голос
/ 16 июня 2019

Одно соединение внутри TransactionScope должно работать как положено.При подключении двух подключений к TransactionScope вы пытаетесь выполнить распределенную транзакцию, которая не поддерживается в .NET Core:

Начиная с версии 2.1, Система.Реализация транзакций в .NET Core не включает поддержку распределенных транзакций, поэтому вы не можете использовать TransactionScope или CommittableTransaction для координации транзакций между несколькими менеджерами ресурсов.

(из статьи Microsoft Docs по EF Core ИспользованиеТранзакции ).

Основанием для отказа от поддержки распределенных транзакций является их зависимость от MSDTC , характерная для Windows.Он не очень хорошо согласуется с дорожной картой .NET Core по созданию межплатформенной структуры.

РЕДАКТИРОВАТЬ: альтернативный подход

В общем, решение полагаться на распределенные транзакции следует принимать сдополнительная осторожность, поскольку эти транзакции легко становятся узкими местами для масштабируемости.В современных архитектурах распределенные транзакции, как правило, не рекомендуется.

В вашем случае, поскольку все ваши ресурсы являются соединениями с одной и той же базой данных, вам фактически не нужны распределенные транзакции.Я бы предложил внедрить (эмбиент) Единицу работы .

Например, у вас может быть экземпляр единицы работы на логическую / бизнес-операцию в вашем приложении.Экземпляр единицы работы будет буферизовать все запрошенные модификации в базе данных (используйте ваши собственные структуры данных для представления модификаций).В конце операции единица работы будет зафиксирована.Операция фиксации будет включать в себя:

  • открытие соединения с БД и транзакцию БД
  • выполнение всей буферизованной модификации с использованием одного соединения с БД
  • фиксация транзакции с БД и закрытие соединения с БД

В качестве другого примера, Entity Framework Core реализует шаблон единиц работы в классе DBContext .

...