Когда мы используем трансацию из System.Transactions (создавая TransationScope для экземпляра) по умолчанию, все Sql-соединения (System.Data.SqlClient.SqlConnection) (но is't также верно для Oracle.DataAccess.OracleConnection) зачисляются сверху открытие. Это называется автоматическим завербованием. Хорошая функция. Но его можно отключить через параметр строки подключения (invist = false). В этом случае соединение, которое открывается, не будет зачислено. Но его можно зачислить вручную позже. Итак, мой вопрос: для какого-то определенного экземпляра SqlConnection, как определить, подключено ли это соединение или нет (в System.Transaction). Я могу посмотреть строку подключения для параметра. Но этого не будет, потому что, как я сказал, соединение может быть завербовано вручную.Как определить, будет ли SqlConnection зачислен в System.Transactions 'tx или нет?
ответ
Рамки, похоже, не позволяют этого.
Возможно, мы могли бы обсудить, почему вам нужно знать эту информацию? TransactionScopeOptions дает вам некоторую гибкость в отношении того, когда создавать транзакции.
Однако, отказавшись от ответа «нет», немного просмотра источника позже, и я создал этот код, который работает. Обратите внимание, что этот код может перестать функционировать в любое время с исправлениями в фреймворк !!!!
static bool IsEnlisted(SqlConnection sqlConnection)
{
object innerConnection = typeof(SqlConnection).GetField("_innerConnection", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).GetValue(sqlConnection);
var enlistedTransactionField =
EnumerateInheritanceChain(innerConnection.GetType())
.Select(t => t.GetField("_enlistedTransaction", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy))
.Where(fi => fi != null)
.First();
object enlistedTransaction = enlistedTransactionField.GetValue(innerConnection);
return enlistedTransaction != null;
}
static IEnumerable<Type> EnumerateInheritanceChain(Type root)
{
for (Type current = root; current != null; current = current.BaseType)
yield return current;
}
Опять же, это использование частных переменных и внутренних классов в рамках .NET. Хотя он работает сегодня, он может и не завтра.
+1 для предупреждения «может не работать завтра». – TcKs 2012-01-11 16:26:38
Хороший вопрос. Мой сценарий заключается в том, что у меня есть сборка, которая представляет собой просто ведро статических методов, которые используют Open SqlConnection и CRUD. Было бы неплохо обеспечить, чтобы SqlConnection был зачислен в транзакцию, прежде чем продолжить, чтобы защитить от логического искажения на уровне приложения вызывающим. Мы можем обнаружить `Transaction.Current! = Null`, и мы можем обнаружить` SqlConnection conn! = Null`, но мы не можем проверить, связано ли соединение с транзакцией. – 2010-12-15 21:50:51