TransactionScope - транзакционный WCF и паралеллизм / многопоточность - PullRequest
0 голосов
/ 24 сентября 2019

Я выискиваю ошибку в нашем проекте, где мы иногда видим данные, сохраняемые в базу данных, даже если возникают исключения и все должно быть откатано.Я спрашивал об этом здесь до и обнаружил, что, если я запрашиваю базу данных для @@trancount сразу после создания нового TransactionScope, и в результате я получаю 0, у меня нет "действительная "транзакция.Он каким-то образом прерывается / откатывается другим потоком.

Код, который я использую для воспроизведения, действительно прост:

Я вызываю этот метод Paralell.For несколько тысяч раз

void Handle()
{
    try
    {
        using (var transaction = new TransactionScope(TransactionScopeOption.Required)
        {
            // Getting @@trancount right here enables us verify whether we have a valid transaction.

            WriteImportantBusinessDataToDatabase("This will sometimes be committed even if the WCF call below fails!");

            // Making a transactional WCF call
            var serviceClient = new Service1Client("WSHttpBinding_IService1");
            serviceClient.DoWork(); // We get an exception here

            WriteImportantBusinessDataToDatabase("We never reach this location");

            transaction.Complete();
        }
    }
    catch (Exception e)
    {
        Logger.Error(e, "Something failed. {message}", e.Message);
    }
}

Служба WCF является транзакционной, с TransactionFlowOption.Mandatory.

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    void DoWork();
}

[ServiceBehavior]
public class Service1 : IService1
{
    [OperationBehavior(TransactionScopeRequired = true)]
    public void DoWork()
    {
        throw new Exception();
    }
}

@@trancount ожидается равным 1 сразу после создания нового TransactionScope.Но иногда @@trancount составляет 0, а в еще более редких случаях 2.Свойство System.Transactions.Transaction.Current.TransactionInformation.Status всегда равно Active, независимо от того, что @@trancount.Вставки в базу данных выполняются просто отлично.Проблема возникает тогда, когда локальная транзакция переводится в распределенную транзакцию с помощью вызова WCF.Затем мы получаем исключение: «Транзакция прервана».

Имя метода Handle правильно указывает на то, что это действительно обработчик NServiceBus, обрабатывающий сотни тысяч сообщений днем ​​и ночью.Мы получаем эту проблему несоответствия только тогда, когда есть проблемы на другой стороне вызова WCF.

Работоспособную версию этой установки можно найти на моем GitHub .

Я воспроизвел проблему со всеми версиями .Net Framework с 4.5.1 до 4.8.Все они дают одинаковые результаты.Кто-нибудь может объяснить, что здесь происходит?

...