6

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

4

1 回答 1

10

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

也许我们可以讨论为什么你需要知道这些信息?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 框架中的私有变量和内部类。虽然它今天有效,但明天可能就不行了。

于 2008-10-14T04:57:19.753 回答