Я выискиваю ошибку в нашем проекте, где мы иногда видим данные, сохраняемые в базу данных, даже если возникают исключения и все должно быть откатано.Я спрашивал об этом здесь до и обнаружил, что, если я запрашиваю базу данных для @@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.Все они дают одинаковые результаты.Кто-нибудь может объяснить, что здесь происходит?