代码之家  ›  专栏  ›  技术社区  ›  Shrike

如何确定是否将SqlConnection登记到System.Transactions的Tx中?

  •  5
  • Shrike  · 技术社区  · 16 年前

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

    1 回复  |  直到 12 年前
        1
  •  8
  •   usr    12 年前

    框架似乎不允许这样做。

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