Transactions 连接池被嵌套的ADO.NET事务损坏(使用MSDTC)
我到处都找不到答案 我将展示一个简单的代码片段,它展示了如何轻松损坏连接池。Transactions 连接池被嵌套的ADO.NET事务损坏(使用MSDTC),transactions,ado.net,transactionscope,msdtc,Transactions,Ado.net,Transactionscope,Msdtc,我到处都找不到答案 我将展示一个简单的代码片段,它展示了如何轻松损坏连接池。 连接池损坏意味着每次打开的新连接尝试都将失败。 要体验我们需要的问题: 在分布式事务中 嵌套的sqlconnection及其在其他sqlconnection和sqltransaction中的sqltransaction 执行回滚(显式或隐式-不提交)嵌套sqltransaction 当连接池损坏时,每个sqlConnection.Open()都会抛出下列之一: SqlException:不允许启动新请求,因为它应该带有
连接池损坏意味着每次打开的新连接尝试都将失败。
要体验我们需要的问题:
SqlException:不允许启动新请求,因为它应该带有有效的事务描述符
Thread.Sleep(10)
放在代码的某个地方,它可能会将收到的异常更改为第二个异常。有时它在没有任何修改的情况下发生变化
如何繁殖
Transaction.Current.EnclestDurable[…]
var connectionStringA=String.Format(@“数据源={0};初始目录={1};集成安全性=True;池化=True;最大池大小=20;登记=True”,
@“\YourServer”,“DataBaseA”);
var connectionStringB=String.Format(@“数据源={0};初始目录={1};集成安全性=True;池=True;最大池大小=20;登记=True”,
@“\YourServer”,“DataBaseB”);
尝试
{
使用(var transactionScope=new transactionScope())
{
//我们需要强制升级到分布式事务:
使用(var sqlConnection=newsqlconnection(connectionStringA))
{
sqlConnection.Open();
}
//您可以将最后3行替换为:(结果相同)
//Transaction.Current.EnstractDurable(Guid.NewGuid()、new EmptyIEnstractmentNotificationImplementation()、EnstractmentOptions.EnstractDuringPrepareRequired);
发生bool错误;
使用(var sqlConnection2=newsqlconnection(connectionStringB))
{
sqlConnection2.Open();
使用(var sqlTransaction2=sqlConnection2.BeginTransaction())
{
使用(var sqlConnection3=newsqlconnection(connectionStringB))
{
sqlConnection3.Open();
使用(var sqlTransaction3=sqlConnection3.BeginTransaction())
{
ErrorOccursed=true;
sqlTransaction3.Rollback();
}
}
如果(!发生错误)
{
sqlTransaction2.Commit();
}
其他的
{
//不执行任何操作,sqlTransaction3已被sqlTransaction2回滚
}
}
}
如果(!发生错误)
transactionScope.Complete();
}
}
捕获(例外e)
{
控制台写入线(e.Message);
}
然后:
(var i=0;i<10;i++)的for//所有尝试都将失败
{
尝试
{
使用(var sqlConnection1=newsqlconnection(connectionStringB))
{
//下面的行将抛出:
//1.SqlException:不允许启动新请求,因为它应该带有有效的事务描述符。
//或
//2.SqlException:分布式事务已完成。请在新事务或空事务中登记此会话。
sqlConnection1.Open();
Console.WriteLine(“连接成功打开”);
}
}
捕获(例外e)
{
控制台写入线(e.Message);
}
}
已知的不良解决方案以及可以观察到的有趣的问题 糟糕的解决方案:
sqlTransaction3.Rollback();ClearPool(sqlConnection3)代码>
TransactionScope
必须包装SqlConnection.Open()
)SqlException离开外部sqltransaction时:回滚事务请求没有相应的BEGIN事务。
被抛出。
try无法捕获该异常。。。捕获…
如何解决? 这个问题使我的web应用程序几乎死机(无法打开任何新的sql连接)。
给出的代码片段是从整个管道中提取出来的,其中也包括对第三方框架的调用。我不能简单地更改代码
- 有人知道到底出了什么问题吗李>
- 是ADO.NET错误吗
- 也许我(和一些框架…)做错了什么
我的环境(似乎不是很重要)
- .NET Framework 4.5
- MS SQL Server 2012
//do nothing, sqlTransaction3 is alread rolled back by sqlTransaction2
sqlTransaction2.Rollback();