SqlParameter有已经包含在另一个SqlParameterCollection - 是否使用(){}作弊?SqlParameter、SqlParameterCollection

2023-09-02 21:54:17 作者:Fickle.(薄情)

当使用使用(){} 如下图所示,假设(原文如此)块 CMD1 不活过第一个的范围使用(){} 块,为什么要第二块抛出一个异常,该消息的 SqlParameter有已包含在另一个SqlParameterCollection?这是否意味着资源和/或处理 - 包括参数(SqlParameterCollection) - 附在 CMD1 当它摧毁了该块结束时没有公布

 使用(VAR康恩=新的SqlConnection(数据源=;初始目录=测试;集成安全性=真))
{
    VAR参数=新的SqlParameter [] {新的SqlParameter(@的ProductId,SqlDbType.Int)};

    使用(VAR CMD1 =新的SqlCommand(选择产品名称FROM产品WHERE的ProductId = @ProductID))
    {
        的foreach(在参数VAR参数)
        {
            cmd1.Parameters.Add(参数);
        }
        // cmd1.Parameters.Clear(); //取消注释,以节省您的肌肤!
    }

    使用(VAR CMD2 =新的SqlCommand(选择复习ProductReviews WHERE的ProductId = @ProductID))
    {
        的foreach(在参数VAR参数)
        {
            cmd2.Parameters.Add(参数);
        }
    }
}
 

注意:做cmd1.Parameters.Clear()只是在最后一个大括号之前的第一个使用(){} 块将节省您的异常(和可能尴尬)。

如果你需要复制您可以使用下面的脚本来创建对象:

  CREATE TABLE产品(
    的ProductId INT IDENTITY(1,1)NOT NULL PRIMARY KEY丛生,
    产品名称为nvarchar(32)NOT NULL)
走

CREATE TABLE ProductReviews(
    ReviewId INT IDENTITY(1,1)NOT NULL PRIMARY KEY丛生,
    的ProductId诠释NOT NULL,
    评论为nvarchar(128)NOT NULL)

走
 
P站 工作细胞 人气排行前10

解决方案

我怀疑的SqlParameter 知道的命令它的一部分,而这种信息是不是清除时,该命令设置,但是的是的,当你调用清除 command.Parameters.Clear()

我个人认为,我会避免重复使用的物品摆在首位,但它是由你:)

While using the using() {} (sic) blocks as shown below, and assuming that cmd1 does not live beyond the scope of the first using() {} block, why should the second block throw an exception with the message The SqlParameter is already contained by another SqlParameterCollection? Does it mean that resources and/or handles - including the Parameters (SqlParameterCollection) - attached to cmd1 are not released when its destroyed at the end of the block?

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);
        }
    }
}

NOTE: Doing cmd1.Parameters.Clear() just before the last brace of the first using() {} block will save you from the exception (and possible embarrassment).

If you need to reproduce you can use the following scripts to create the objects:

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

解决方案

I suspect that SqlParameter "knows" which command it's part of, and that that information isn't cleared when the command is disposed, but is cleared when you call command.Parameters.Clear().

Personally I think I'd avoid reusing the objects in the first place, but it's up to you :)