Соединение с использованием enlist = false не закрывается после ручного включения в распределенную транзакцию

У меня есть контекст распределенной транзакции, использующий ServiceDomain. Внутри него я открываю соединение SQL со строкой соединения, указывающей Enlist=false, чтобы оно не автоматически включалось в транзакцию. Затем, если я вручную включу соединение в распределенную транзакцию с помощью EnlistDistributedTransaction, соединение не будет закрыто, что может закончиться InvalidOperationException с:

Истекло время ожидания. Период тайм-аута истек до получения соединения из пула. Это могло произойти из-за того, что все соединения в пуле использовались и был достигнут максимальный размер пула.

Попробуйте следующее:

try
{
    var configuration = new ServiceConfig
        {
            Transaction = TransactionOption.Required,
            TransactionTimeout = 1000
        };
    ServiceDomain.Enter(configuration);

    for (var i = 0; i < 500; ++i)
    {
        Console.WriteLine(i);
        using (var conn = new SqlConnection("Data Source=localhost;Initial Catalog=dotest;Integrated Security=SSPI;Enlist=False;"))
        {
            conn.Open();
            if (i % 2 == 0) conn.EnlistDistributedTransaction((ITransaction) ContextUtil.Transaction);
            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = "INSERT INTO [Test]([ID]) VALUES(@num)";
                cmd.Parameters.AddWithValue("@num", i);
                cmd.ExecuteNonQuery();
            }
        }
    }

    ContextUtil.SetAbort();
}
finally
{
    ServiceDomain.Leave();
}

Это застревает (и умирает после тайм-аута) на 200 подключениях, поскольку все 100 подключенных подключений, очевидно, не закрываются (а размер пула подключений по умолчанию равен 100). (Обратите внимание, что вы можете полностью удалить команду, если хотите протестировать ее, не создавая таблицу.)

Что я упускаю или делаю не так?


person Mormegil    schedule 12.04.2011    source источник
comment
Вы пытались вместо этого использовать EnlistTransaction? Предполагается, что он также будет обрабатывать распределенный.   -  person Simon Mourier    schedule 20.04.2011
comment
@Simon Mourier - EnlistTransaction обрабатывает System.Transactions.Transaction, но в моем случае используется System.EnterpriseServices.ITransaction, поэтому (AFAICT) это не вариант.   -  person Mormegil    schedule 21.04.2011


Ответы (1)


Попробуйте установить conn.EnlistDistributedTransaction(null); в конце выполнения запроса.

using (var conn = new SqlConnection("Data Source=localhost;Initial Catalog=dotest;Integrated Security=SSPI;Enlist=False;"))
{
    conn.Open();
    if (i % 2 == 0) conn.EnlistDistributedTransaction((ITransaction) ContextUtil.Transaction);
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "INSERT INTO [Test]([ID]) VALUES(@num)";
        cmd.Parameters.AddWithValue("@num", i);
        cmd.ExecuteNonQuery();
    }
   conn.EnlistDistributedTransaction(null);
}
person Priyank    schedule 26.04.2011
comment
Спасибо, это всего лишь обходной путь (я не думаю, что должен это делать, документация по EnlistDistributedTransaction даже не говорит, что я могу передать значение null), но, по крайней мере, он работает. Я назначил награду, так как в оставшиеся 5 минут лучшего ответа не будет. ;-) - person Mormegil; 26.04.2011