在使用如下所示的using() {}
(sic)块时,假设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);
}
}
}
注意:在第一个的最后一个括号之前使用() {}代码块执行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
发布于 2011-10-20 22:53:38
我怀疑SqlParameter
“知道”它是哪个命令的一部分,并且该信息不会在命令被释放时清除,而是在您调用command.Parameters.Clear()
时清除。
就我个人而言,我认为我一开始就会避免重用对象,但这取决于您:)
发布于 2011-10-20 22:56:31
使用块并不能确保一个对象被“销毁”,只需要调用Dispose()
方法即可。这实际上做了什么取决于具体的实现,在这种情况下,它显然不会清空集合。这样做的目的是确保不会被垃圾回收器清理的非托管资源被正确释放。由于参数集合不是非托管资源,因此它并不完全令人惊讶,它不会被dispose方法清除。
发布于 2015-10-08 02:52:30
在执行之后添加cmd.Parameters.Clear();应该没问题。
https://stackoverflow.com/questions/7837762
复制相似问题