Използвам комбинация от 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 има грешка при опит за отваряне на втора връзка, която не е в пула?