[Test]
public void TransactionScopeTest()
{
using (new TransactionScope())
{
using (var db = new DbManager())
{
db.SetSpCommand("GetAllCustomers");
}
}
}
Вылетает:
FreeTests.TransactionScopeTest : FailedDbManager: Operation 'OpenConnection' throws exception 'BLToolkit.Data.DataException: Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported. ---> System.NotSupportedException: Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported.
at MySql.Data.MySqlClient.MySqlConnection.Open() in c:\VCProjects\MySQL Connector .NET 6.0.3\MySql.Data\Provider\Source\Connection.cs:line 454
at BLToolkit.Data.DbManager.ExecuteOperation(OperationType operationType, Action operation) in c:\VCProjects\BLToolkit\Source\Data\DbManager.cs:line 4002
--- End of inner exception stack trace ---'
System.NotSupportedException: Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported.
at MySql.Data.MySqlClient.MySqlConnection.Open() in Connection.cs: line 454
at BLToolkit.Data.DbManager.ExecuteOperation(OperationType operationType, Action operation) in DbManager.cs: line 4002
BLToolkit.Data.DataException: Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported.
at BLToolkit.Data.DbManager.OnOperationException(OperationType op, DataException ex) in DbManager.cs: line 530
at BLToolkit.Data.DbManager.HandleOperationException(OperationType op, Exception ex) in DbManager.cs: line 4047
at BLToolkit.Data.DbManager.ExecuteOperation(OperationType operationType, Action operation) in DbManager.cs: line 4007
at BLToolkit.Data.DbManager.DiscoverSpParameters(String spName, Boolean includeReturnValueParameter) in DbManager.cs: line 768
at BLToolkit.Data.DbManager.GetSpParameters(String spName, Boolean includeReturnValueParameter) in DbManager.cs: line 846
at BLToolkit.Data.DbManager.CreateSpParameters(String spName, Object[] parameterValues) in DbManager.cs: line 561
at BLToolkit.Data.DbManager.SetSpCommand(CommandAction commandAction, String spName, Object[] parameterValues) in DbManager.cs: line 1802
at BLToolkit.Data.DbManager.SetSpCommand(String spName, Object[] parameterValues) in DbManager.cs: line 1878
at RA.Tests.FreeTests.TransactionScopeTest() in FreeTests.cs: line 39
Ключевые вызовы: DiscoverSpParameters() -> ExecuteOperation(OperationType.OpenConnection, con.Open); -> и дальше уже в MySqlConnection.Open() (MySql.Data.MySqlClient namespace) есть такой участок:
// if we are auto enlisting in a current transaction, then we will be
// treating the connection as pooledif (settings.AutoEnlist && Transaction.Current != null)
{
driver = DriverTransactionManager.GetDriverInTransaction(Transaction.Current);
if (driver != null &&
(driver.IsInActiveUse ||
!driver.Settings.EquivalentTo(this.Settings)))
throw new NotSupportedException(Resources.MultipleConnectionsInTransactionNotSupported);
}
driver.IsInActiveUse = true, поэтому выбрасывается исключение.
Добавил параметр в метод SetSpCommand, позволяющий проверять параметры процедуры на существующем соединении и соответствующую настройку Configuration.OpenNewConnectionToDiscoverParameters, которая по умолчанию == true.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, MozgC, Вы писали:
IT>Добавил параметр в метод SetSpCommand, позволяющий проверять параметры процедуры на существующем соединении и соответствующую настройку Configuration.OpenNewConnectionToDiscoverParameters, которая по умолчанию == true.
Спасибо за оперативность, но к сожалению из-за все того же блока в методе MySqlConnection.Open() при открытии второго подключения возникает исключение:
if (settings.AutoEnlist && Transaction.Current != null)
{
driver = DriverTransactionManager.GetDriverInTransaction(Transaction.Current);
if (driver != null &&
(driver.IsInActiveUse ||
!driver.Settings.EquivalentTo(this.Settings)))
throw new NotSupportedException(Resources.MultipleConnectionsInTransactionNotSupported);
}
из текущей транзакции, вызыванной TransactionScope, берется драйвер, у которого IsInActiveUse = true, и получаем все то же исключение.
Но, если перед этим выставить Configuration.OpenNewConnectionToDiscoverParameters в false :
Configuration.OpenNewConnectionToDiscoverParameters = true;
using (new TransactionScope())
{
using (var db = new DbManager())
{
DataTable customers = db.SetSpCommand("GetAllCustomers").ExecuteDataTable();
}
}
то отрабатывает нормально
Я что-то не так понял по поводу OpenNewConnectionToDiscoverParameters или надо поправить? Или как раз в случае MySql надо в false выставлять этот параметр и так задумано?
А вообще по каким причинам по умолчанию открывается новое соединение для получения параметров? Имхо это странно.
Если этому есть объяснение, то возможно надо подделать DataProviderBase чтобы тот решал, открывать ли новое соединение в случае имеющегося TransactionScope. И в MySqlDataProvider оверрайдить так, чтобы в случае имеющегося TransactionScope новое соединение не открывалось.
Здравствуйте, MozgC, Вы писали:
MC>Я что-то не так понял по поводу OpenNewConnectionToDiscoverParameters или надо поправить? Или как раз в случае MySql надо в false выставлять этот параметр и так задумано?
Задумано так. Либо задаём OpenNewConnectionToDiscoverParameters один раз и не паримся, либо передаём это значение как параметр каждый раз при каждом вызове, который может повлечь за собой вызов DiscoverSpParametr. Возможно я не везде протащил этот параметр для второго варианта.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, MozgC, Вы писали:
MC>А вообще по каким причинам по умолчанию открывается новое соединение для получения параметров? Имхо это странно. MC>Если этому есть объяснение, то возможно надо подделать DataProviderBase чтобы тот решал, открывать ли новое соединение в случае имеющегося TransactionScope. И в MySqlDataProvider оверрайдить так, чтобы в случае имеющегося TransactionScope новое соединение не открывалось.
На одном соединении можно выполнить несколько команд подряд, при этом результаты выполнения этих команд могут быть использованы далее. При этом у нас между запросами вклинивается DiscoveryParameters, которая может разрушить текущий контекст.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
MC>>А вообще по каким причинам по умолчанию открывается новое соединение для получения параметров? Имхо это странно. MC>>Если этому есть объяснение, то возможно надо подделать DataProviderBase чтобы тот решал, открывать ли новое соединение в случае имеющегося TransactionScope. И в MySqlDataProvider оверрайдить так, чтобы в случае имеющегося TransactionScope новое соединение не открывалось.
IT>На одном соединении можно выполнить несколько команд подряд, при этом результаты выполнения этих команд могут быть использованы далее. При этом у нас между запросами вклинивается DiscoveryParameters, которая может разрушить текущий контекст.
Думаю, что это спорный момент.
А что думаешь по поводу того, чтобы для MySql, в случае текущего TransactionScope, OpenNewConnectionToDiscoverParameters выставлялся в false?
Здравствуйте, MozgC, Вы писали:
MC>А что думаешь по поводу того, чтобы для MySql, в случае текущего TransactionScope, OpenNewConnectionToDiscoverParameters выставлялся в false?
Для TransactionScope можно было бы вообще всегда выставлять false, только не понятно, как определить, что мы в TransactionScope.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>как определить, что мы в TransactionScope.
Видимо смотреть Transaction.Current. Но тут как я понимаю Transaction.Current может быть выставлено и самостоятельно, без TransactionScope. Другое дело что может и пофигу.