How to determine if SqlConnection will be enrolled in the tx of SystemTransactions or not?

When we use the translation from System.Transactions (by creating a TransationScope for the instance) by default, all Sql connections (System.Data.SqlClient.SqlConnection) (but is't also true for Oracle.DataAccess.OracleConnection) are credited to the opening. This is called automatic recruitment. Good feature. But it can be disabled through the connection string parameter (invist = false). In this case, the connection that opens will not be credited. But you can add it manually later. Therefore, my question is: for a specific SqlConnection instance, how to determine if this connection is connected or not (in System.Transaction). I can see the connection string for the parameter. But this will not be done, because, as I said, the connection can be recruited manually.

+5
source share
1 answer

The framework does not seem to allow this.

Perhaps we could discuss why you need to know this information? TransactionScopeOptions gives you some flexibility as to when to create transactions.

However, abandoning the no answer, I looked at the source a bit later, and I created this code that works. Please note that this code may stop functioning at any time with corrections in the framework !!!!

    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;
    }

Again, this is the use of private variables and inner classes within .NET. Although he works today, he may not tomorrow.

+7
source

All Articles