当我们默认使用来自System.Transactions的转换(为实例创建TransationScope)时,所有Sql-connections(System.Data.SqlClient.SqlConnection)(但对于Oracle.DataAccess.OracleConnection也是如此)都会在打开时登记.这就是所谓的自动入伍.不错的功能.但它可以通过连接字符串的参数(enlist = false)关闭.在这种情况下,打开的连接将不会被列入.但它可以在以后手动登记.所以我的问题是:对于某些给定的SqlConnection实例,我如何确定该连接是否已登记(进入System.Transaction).我可以查看参数的连接字符串.但这不行,因为我说连接可以手动登记.
该框架似乎不允许这样做.
也许我们可以讨论为什么你需要知道这些信息?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 IEnumerableEnumerateInheritanceChain(Type root) { for (Type current = root; current != null; current = current.BaseType) yield return current; }
同样,这是在.NET框架中使用私有变量和内部类.虽然它今天有用,但明天可能不会.