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