Я провел несколько тестов с тех пор, как задал этот вопрос, и нашел большинство, если не все ответы самостоятельно, поскольку никто не ответил. Пожалуйста, дайте мне знать, если я что-то пропустил.
Q1. Да, если в строке подключения не указано "enlist = false". Пул соединений находит пригодное для использования соединение. Подходящее соединение - это соединение, которое не зачислено в транзакцию, или соединение, зачисленное в той же транзакции.
Q2. Второе соединение является независимым соединением, которое участвует в той же транзакции. Я не уверен в взаимодействии команд на этих двух соединениях, так как они работают с одной и той же базой данных, но я думаю, что могут возникнуть ошибки, если команды будут выполнены для обеих одновременно: ошибки, подобные "Контекст транзакции используется другим сеансом "
Q3. Да, оно преобразуется в распределенную транзакцию, поэтому включение нескольких соединений, даже с одной и той же строкой соединения, превращает их в распределенную транзакцию, что можно подтвердить, проверив ненулевой GUID в Transaction.Current.TransactionInformation.DistributedIdentifier.
* Обновление: я где-то читал, что это исправлено в SQL Server 2008, поэтому MSDTC не используется, когда для обоих подключений используется одна и та же строка подключения (если оба подключения не открыты одновременно). Это позволяет вам открывать соединение и закрывать его несколько раз в рамках транзакции, что может лучше использовать пул соединений, открывая соединения как можно позже и закрывая их как можно скорее.
Q4. Нет. Соединение, открытое при отсутствии активной области транзакции, не будет автоматически зачислено во вновь созданную область транзакции.
Q5. Нет. Если вы не откроете соединение в области транзакции или не подключите существующее соединение в области, в основном, нет транзакции. Чтобы ваши команды могли участвовать в транзакции, ваше соединение должно быть автоматически или вручную зачислено в область транзакции.
Q6. Да, команды на соединении, не участвующем в транзакции, фиксируются как выпущенные, даже если код выполнен в блоке области транзакции, который был откатан. Если соединение не зачислено в текущую область транзакции, оно не участвует в транзакции, поэтому фиксация или откат транзакции не окажут влияния на команды, выполненные для соединения, не включенного в область транзакции ... как this парень узнал . Это очень трудно определить, если вы не понимаете процесс автоматического зачисления: он происходит только тогда, когда соединение открыто внутри активной области транзакции.
Q7. Да. Существующее соединение может быть явно зачислено в текущую область транзакции путем вызова EnlistTransaction (Transaction.Current). Вы также можете подключить соединение в отдельном потоке в транзакции с помощью DependentTransaction, но, как и раньше, я не уверен, как могут взаимодействовать два соединения, участвующих в одной транзакции, с одной и той же базой данных ... и могут возникать ошибки, и конечно, второе зачисленное соединение приводит к тому, что транзакция переходит в распределенную транзакцию.
Q8. Возможно, возникла ошибка.Если использовался TransactionScopeOption.Required и соединение уже было зачислено в транзакцию области транзакции, то ошибки нет;фактически для этой области не было создано новой транзакции, и количество транзакций (@@ trancount) не увеличивается.Однако, если вы используете TransactionScopeOption.RequiresNew, вы получите полезное сообщение об ошибке при попытке включить соединение в новую транзакцию области транзакции: «В данный момент в транзакции подключена транзакция. Завершите текущую транзакцию и повторите попытку».И да, если вы завершите транзакцию, в которую зачислено соединение, вы можете безопасно подключить соединение к новой транзакции. Обновление: если вы ранее вызывали BeginTransaction для соединения, при попытке зачисления в новую транзакцию области транзакции выдается немного другая ошибка: «Невозможно подключиться к транзакции, так как в соединении выполняется локальная транзакция. Завершитьлокальная транзакция и повторите попытку. "С другой стороны, вы можете безопасно вызывать BeginTransaction для SqlConnection, пока он зачислен в транзакцию области транзакции, и это фактически увеличит @@ trancount на единицу, в отличие от использования опции Required области вложенной транзакции, которая не вызывает егоувеличение.Интересно, что если вы затем продолжите создавать другую вложенную область транзакции с параметром Required, вы не получите ошибку, потому что ничего не изменится в результате уже имеющейся транзакции активной области транзакции (помните, @@ trancount не увеличивается, когда транзакциятранзакция области уже активна и используется опция Обязательный).
Q9. Да.Команды участвуют в любой транзакции, в которую включено соединение, независимо от того, какая область активной транзакции находится в коде C #.