【发布时间】:2011-12-11 20:56:34
【问题描述】:
虽然使用如下所示的using() {}(原文如此)块,并假设cmd1 不会超出第一个using() {} 块的范围,那么为什么第二个块会抛出带有消息的异常
SqlParameter 已被另一个 SqlParameterCollection 包含
这是否意味着附加到 cmd1 的资源和/或句柄(包括参数 (SqlParameterCollection))在块末尾被销毁时不会被释放?
using (var conn = new SqlConnection("Data Source=.;Initial Catalog=Test;Integrated Security=True"))
{
var parameters = new SqlParameter[] { new SqlParameter("@ProductId", SqlDbType.Int ) };
using(var cmd1 = new SqlCommand("SELECT ProductName FROM Products WHERE ProductId = @ProductId"))
{
foreach (var parameter in parameters)
{
cmd1.Parameters.Add(parameter);
}
// cmd1.Parameters.Clear(); // uncomment to save your skin!
}
using (var cmd2 = new SqlCommand("SELECT Review FROM ProductReviews WHERE ProductId = @ProductId"))
{
foreach (var parameter in parameters)
{
cmd2.Parameters.Add(parameter);
}
}
}
注意: 在第一个 using() {} 块的最后一个大括号之前执行 cmd1.Parameters.Clear() 将使您免于异常(并且可能尴尬)。
如果您需要重现,您可以使用以下脚本来创建对象:
CREATE TABLE Products
(
ProductId int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
ProductName nvarchar(32) NOT NULL
)
GO
CREATE TABLE ProductReviews
(
ReviewId int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
ProductId int NOT NULL,
Review nvarchar(128) NOT NULL
)
GO
【问题讨论】:
-
我也看到了这个,但是那个修复没有奏效。令人沮丧。而且我只使用一个 cmd 对象,没有重复使用。它被包裹在一个异步重试循环中,所以它可能是相同的根本原因,只是没有以相同的方式避免。
标签: c# .net sql-server ado.net