1. ホーム
  2. c#

[解決済み] SqlParameter は、すでに別の SqlParameterCollection に含まれています - using() {} は、不正行為ですか?

2022-01-30 04:01:11

質問

を使用しているときに using() {} (を想定して、以下のようなブロックを作成します。 cmd1 の範囲を超えて生きているわけではありません。 using() {} というメッセージとともに例外を投げる必要があるのでしょうか?

SqlParameter はすでに別の SqlParameterCollection に含まれています。

これは、パラメータを含むリソースやハンドル( SqlParameterCollection に接続されている cmd1 は、ブロックの最後で破壊されたときに解放されないのですか?

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 cmd1.Parameters.Clear()を最初の中括弧の直前で実行すること。 using() {} を使えば、例外を回避できます(恥をかく可能性もあります)。

再現が必要な場合は、以下のスクリプトを使用してオブジェクトを作成することができます。

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

解決方法は?

私は、次のように考えています。 SqlParameter どのコマンドの一部であるかを知っており、その情報はコマンドが破棄されてもクリアされませんが を呼び出すとクリアされます。 command.Parameters.Clear() .

個人的には、そもそもオブジェクトの再利用は避けた方がいいと思いますが、それはあなた次第です :)