Попытки открыть несколько соединений Oracle в контексте TransactionScope приводят к ORA-12514.

Я использую комбинацию Dapper и Quartz.Net (планировщик) для сохранения информации о простом объекте в базе данных 11gR2 (Quartz самодостаточен и сам открывает и закрывает соединения, вызов Dapper выполняет процедуру через соединение, поддерживаемое единица работы, которая также контролирует транзакцию).

Я использую санкционированный Microsoft метод TransactionScope, чтобы инициировать транзакцию, и для подключений настроено автоматическое включение в распределенную транзакцию, если она уже запущена. Я использую управляемый драйвер Oracle для 12c, поэтому у меня не установлен клиент 12c.

Вот что странно. Первое соединение всегда открывается успешно и включается в транзакцию, в зависимости от того, как я это делаю. Второй всегда дает сбой и выдает ошибку ORA-12514.

Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-12514: TNS:listener does not currently know of service requested in connect descriptor ---> OracleInternal.Network.NetworkException (0x000030E2): ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
   at OracleInternal.Network.OracleCommunication.DoConnect(String tnsDescriptor)
   at OracleInternal.Network.OracleCommunication.Connect(String tnsDescriptor, Boolean externalAuth, String instanceName)
   at OracleInternal.ServiceObjects.OracleConnectionImpl.Connect(ConnectionString cs, Boolean bOpenEndUserSession, String instanceName)
   at OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
   at OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
   at OracleInternal.ConnectionPool.PoolManager`3.GetEnlisted(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp)
   at OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword)
   at Oracle.ManagedDataAccess.Client.OracleConnection.Open()

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

using (var tx = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions {IsolationLevel = isolationLevel})
{
    connection.Open(); // works, BUT if I move this line under the next one, the calendar save will succeed and this will fail.
    quartzScheduler.AddCalendar(calendar.Name, c1, true, true); // calls underlying Quartz class that opens a connection, saves to the db and closes a connection - *** this line will fail ***
    _repository.Save(_connection);
}

Служба MS DTC работает локально (Windows 7), служба Oracle MTS Recovery (для 11 клиента) установлена ​​и также работает.

Я прочитал справку, прилагаемую к драйверу Oracle, и, как было предложено, добавил как 64-разрядные, так и 32-разрядные драйверы в папки x86 и x64 в проекте и установил постоянное копирование как часть сборки; однако я не думаю, что захожу так далеко - похоже, что второе соединение всегда выходит из строя, и я не могу определить, почему.

У меня заканчиваются идеи, помощь в этой области кажется довольно скудной, если вы выходите за рамки сохранения одной конкретной схемы и базы данных.

Все идеи приветствуются, заранее спасибо!

Дополнительное редактирование

Этим утром я также попытался провести простой тест для продвижения стандартной транзакции, открыв два соединения в рамках транзакции. Возникает та же проблема:

using (var ts = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions {IsolationLevel = IsolationLevel.ReadCommitted}, EnterpriseServicesInteropOption.Full)) {
   var currentTransaction = Transaction.Current;
   var identifier = currentTransaction.TransactionInformation.DistributedIdentifier;
   using (var oc1 = new CustomOracleConnection(_connectionString, 50, 50)) {
      oc1.Open();
      using (var oc2 = new CustomOracleConnection(_quartzString, 50, 50)) {
         oc2.Open();
      }
   }
}

Глядя на информацию о трассировке, я подумал, связано ли это с объединением. Я попытался открыть второе соединение сначала за пределами области транзакции, а затем снова попробовал все это. Это работает ... так что, похоже, проблема в том, что у драйвера Oracle есть ошибка при попытке открыть второе соединение, которого нет в пуле?


person burgen    schedule 27.08.2015    source источник


Ответы (1)


Проконсультировавшись с Oracle, я узнал, что:
a) Это общепризнанная ошибка драйвера Oracle, которая была исправлена ​​в их кодовой базе, но вряд ли выпустит 4-й выпуск, поэтому может пройти некоторое время, прежде чем мы см. его в версии 5.
b) Временное решение - использовать SERVICE_NAME вместо SID при подключении к базе данных.

Для получения полной информации см. Форум Oracle ODP.Net https://community.oracle.com/message/13275819

person burgen    schedule 30.08.2015
comment
привет, @burgen. Вы знаете, выпущено ли это сейчас и в какой версии? Я специально просмотрел примечания к выпуску и исправления ошибок и не заметил, чтобы об этом упоминалось. Я использую 12.1.24160419 и периодически вижу эту проблему с Quartz.net. - person Igor Pashchuk; 14.07.2017
comment
Привет, @IgorPashchuk, к сожалению, я не знаю, прошло некоторое время с тех пор, как я изначально запрашивал это в Oracle, но вы можете попробовать ответить на мою исходную ветку форума ODP.Net и посмотреть, получите ли вы ответ - пожалуйста, дайте нам знать! - person burgen; 17.07.2017