如何确定是否将SqlConnection登入System.Transactions的tx?

Shr*_*ike 5 .net ado.net msdtc transactions .net-2.0

当我们默认使用来自System.Transactions的转换(为实例创建TransationScope)时,所有Sql-connections(System.Data.SqlClient.SqlConnection)(但对于Oracle.DataAccess.OracleConnection也是如此)都会在打开时登记.这就是所谓的自动入伍.不错的功能.但它可以通过连接字符串的参数(enlist = false)关闭.在这种情况下,打开的连接将不会被列入.但它可以在以后手动登记.所以我的问题是:对于某些给定的SqlConnection实例,我如何确定该连接是否已登记(进入System.Transaction).我可以查看参数的连接字符串.但这不行,因为我说连接可以手动登记.

The*_*edi 9

该框架似乎不允许这样做.

也许我们可以讨论为什么你需要知道这些信息?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;
    }
Run Code Online (Sandbox Code Playgroud)

同样,这是在.NET框架中使用私有变量和内部类.虽然它今天有用,但明天可能不会.