Как открыть несколько соединений sql с ADO при обработке сообщения nservicebus

У меня есть обработчик сообщений, использующий NServiceBus, которому необходимо выполнять код SQL в двух разных базах данных. Строки подключения имеют разные исходные каталоги, но в остальном идентичны.

Когда сообщение получено, первое соединение sql открывается успешно, но второе соединение sql вызывает следующее исключение при вызове .Open.

Доступ к сети для диспетчера распределенных транзакций (MSDTC) отключен. Включите DTC для доступа к сети в конфигурации безопасности для MSDTC с помощью инструмента администрирования служб компонентов.

Мы не используем MSDTC.

Вот код, который не работает. Это не сработает на connB.Open ()

public void Handle(MyMsgCmd message)
        {
            using (SqlConnection connA = new SqlConnection(myConnectionStringA))
            {
                connA.Open();
            }

            using (SqlConnection connB = new SqlConnection(myConnectionStringB))
            {
                connB.Open();
            }
        }

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

Каждое из этих соединений будет успешно открываться при открытии первым или при открытии само по себе, но всякий раз, когда присутствует второе соединение, второе соединение всегда не открывается с одним и тем же исключением, даже если оно заведомо исправно.

Требуется ли дополнительная настройка для последовательного открытия нескольких соединений с NServiceBus?


person Michael Mac McCann    schedule 16.08.2018    source источник


Ответы (2)


Похоже, что по умолчанию NServiceBus обертывает каждый обработчик сообщений в транзакции, что приводит к сбою запросов к различным соединениям с базой данных внутри одного и того же обработчика сообщений, если MSDTC не включен.

Я могу отключить это с помощью BusConfiguration.Transactions (). DoNotWrapHandlersExecutionInATransactionScope ()

person Michael Mac McCann    schedule 16.08.2018

Дополнительную информацию о транзакции можно найти в документации NServiceBus.

Это не связано исключительно с NServiceBus, мы просто предоставляем различные способы подключения к транспорту (например, MSMQ, служебная шина Azure и т. Д.), Персистеру и вашей собственной базе данных.

Но даже без NServiceBus при подключении к двум базам данных вам понадобится либо распределенная транзакция, либо убедитесь, что транзакция не эскалирована до распределенной транзакции. Дело в том, что без распределенных транзакций, когда одна транзакция успешно фиксируется, другая транзакция может потерпеть неудачу. В результате ваши две базы данных больше не синхронизированы или согласованы.

Если заказы в DatabaseA хранятся, а инвентарь отслеживается в DatabaseB, вы можете вычесть 1 из инвентаря, но заказ может никогда не быть сохранен из-за сбоя транзакции. Компенсировать это нужно самостоятельно без распределенных транзакций.

Нельзя сказать, что распределенные транзакции всегда подходят. Вероятно, вы не используете их, потому что они не нравятся вашему администратору баз данных. MSDTC всегда помещает сериализуемые транзакции в ваши данные, которые имеют самые тяжелые блокировки. Чем дольше вы будете держать их открытыми, тем больше одновременных транзакций придется ждать. Возможны огромные проблемы с производительностью вашего программного обеспечения.

С другой стороны, создание компенсационных транзакций может быть очень и очень трудным. И только подумайте о том, что DatabaseA может выйти из строя, DatabaseB может преуспеть. Но что происходит с сообщением? Это ушло из очереди? Или он останется в очереди и снова будет обработан? Будет ли DatabaseB снова успешной из-за возможного дублирования данных?

К счастью, вы уже используете NServiceBus. Вы можете попробовать функцию исходящих сообщений, которая может помочь решить некоторые из эти вопросы.

person Dennis van der Stelt    schedule 17.08.2018