Я использую комбинацию 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 есть ошибка при попытке открыть второе соединение, которого нет в пуле?