Опитите за отваряне на множество 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 папки в проекта и настроих винаги да копирам като част от компилацията; въпреки това не мисля, че дори стигам дотук - все едно втората връзка винаги се проваля и не мога да определя защо.

Идеите ми се изчерпват, помощта в тази област изглежда доста оскъдна, след като излезете извън запазването в една конкретна схема и db.

Всички идеи са добре дошли, благодаря предварително!

Допълнителна редакция

Тази сутрин също опитах прост тест за насърчаване на стандартна транзакция чрез отваряне на две връзки в обхвата на транзакция. Възниква същия проблем:

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