Как определить, зачислен ли SqlConnection в tx System.Transactions или нет?
Когда мы используем переход из System.Transactions (создавая TransationScope для экземпляра) по умолчанию, все Sql-соединения (System.Data.SqlClient.SqlConnection) (но это также не относится к Oracle.DataAccess.OracleConnection) зачисляются при открытии, Это называется автоматической вербовкой. Хорошая особенность. Но его можно отключить через параметр строки соединения (enlist=false). В этом случае открытое соединение не будет зачислено. Но это может быть зачислено вручную позже. Поэтому мой вопрос: для какого-то конкретного экземпляра SqlConnection, как я могу определить, зачислено ли это соединение или нет (в System.Transaction). Я могу посмотреть на строку подключения для параметра. Но это не сработает, потому что, как я сказал, соединение может быть установлено вручную.
1 ответ
Структура, кажется, не позволяет это.
Возможно, мы могли бы обсудить, почему вам нужно знать эту информацию? 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. Хотя сегодня это работает, возможно, не завтра.