C # управление транзакцией через несколько баз данных

Скажем, у меня есть приложение Windows Form, которое связано с n базами данных, при этом n соединений открываются одновременно.

То, что я ищу, – это сделать транзакцию со всеми этими базами данных за один раз.

Например, если бы у меня было 2 подключения к базе данных:

 using (ITransaction tx1 = session1.OpenTransaction()) { using (ITransaction tx2 = session2.OpenTransaction()) { // Do the query thingy here } } 

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

Я хотел бы зациклить весь зарегистрированный сеанс и завершить его в службе, возможно, что-то вроде этого:

 class TransactionManager { private ISession[] _sessions; public TransactionManager(string[] connectionStrings) { // Initialize the sessions here } public function DoTransaction(string query) { foreach (ISession session in _sessions) { // What to do here? Using? Try-catch? } } } 

Если бы мне пришлось использовать использование в цикле foreach , это означало бы, что если соединение A успешно, но соединение B не было, тогда будет отключено только соединение B.

    Кажется, вы можете изобретать TransactionScope . Выполнение всего этого в рамках единицы работы прост *:

      using (TransactionScope scope = new TransactionScope()) { ... Do Stuff with Connection 1 using SqlDataReader ... Do Stuff with Connection 2 using Entity Framework ... Do Stuff with Connection 3 on another Oracle Database ... And for good measure do some stuff in MSMQ or other DTC resource scope.Complete(); // If you are happy } 

    Stuff не обязательно должен быть встроенным – он может быть в другом classе или другой сборке. Нет необходимости явно регистрировать подключения к базе данных или очереди с TransactionScope – все происходит automagically , при условии, что ресурсы, которые вы используете, могут подключаться к внешней транзакции .

    Теперь небольшая печать:

    • * одновременном использовании нескольких соединений с базой данных или разных цепочек соединений или нескольких технологий для этого требуется 2 фазовых фиксации и переход на транзакцию DTC , чтобы обеспечить ACID по всем ресурсам. Сам DTC имеет намного более мелкий шрифт и создает множество проблем в корпоративной сети , таких как брандмауэры , кластеризация , конфигурация безопасности и ошибки .
    • Однако при транзакциях с низким весом на сервере MS Sql, если вы можете сохранить все свои подключения с использованием одной и той же базы данных и тех же параметров строки подключения и закрыть каждое соединение, прежде чем открывать следующее, тогда вы можете избежать DTC .

    • Поддержание транзакции по нескольким ресурсам ACID будет неизменно поддерживать блокировки этих ресурсов до тех пор, пока транзакция не будет завершена или не откат. Это часто не способствует добрососедству на предприятиях большого объема, поэтому обязательно рассмотрите последствия блокировки.

    • Если Stuff выполняется через несколько streamов, вам нужно будет привязать DependentTransaction

    • Последний момент, о котором стоит упомянуть, – это уровень изоляции по умолчанию, при котором TransactionScope является Serializable, который подвержен взаимоблокировкам. В большинстве некритических сценариев вы, вероятно, сможете отбросить это до Read Committed .

    используйте TransactionScope, он позаботится о совершении или откате всех включенных транзакций:

     using (var ts = new TransactionScope()) { ... // your old code ts.Complete() } 
    Давайте будем гением компьютера.