2011-10-20 59 views
51

なぜ第二のブロックスローする必要があり、{}ブロック)(以下に示すように(){}(SIC)ブロックを使用してを使用し、そしてCMD1を使用して、最初の範囲を超えて住んでいないと仮定しているがメッセージの例外SqlParameterは既に別のSqlParameterCollectionに含まれていますか? cmd1に添付されているパラメータ(SqlParameterCollection)を含むリソースやハンドルが、ブロックの最後に破棄されたときに解放されないことを意味しますか?SqlParameterは既に別のSqlParameterCollectionに含まれています - using(){}は不正ですか?

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 

答えて

66

私はSqlParameterが、それはの一部だwhichコマンド「を知っている」、とするとき、その情報がクリアされていないことと思われますコマンドは廃棄されますが、command.Parameters.Clear()に電話するとにクリアされます。

個人的に私は私が最初の場所でのオブジェクトの再利用を避けるだろうと思うが、それはあなた次第です:)

+0

ありがとうございました。私はそれが事実だと思った。それはまた、SqlParameterが、それが良いことであると確信していない廃棄オブジェクトに自身を関連付けることを意味します。 –

+0

@JohnGathogo:関連付けが形成された後に処理されるオブジェクトに関連付けられています。確かに理想的ではありません。 –

+4

他のメモ。最初の 'using'ブロックを終了する前に' Clear'を実行しなければなりませんでした。私の2番目の 'using'ブロックを入力すると、このエラーが発生しました。 – Snekse

6

ブロックを使用Dispose()メソッドが呼び出されるだけであること、オブジェクトが「破壊」されることを保証しません。 。実際には具体的な実装まであり、この場合はコレクションを空にしません。この考え方は、ガベージコレクタによってクリーンアップされないアンマネージドリソースが正しく配置されるようにすることです。 Parametersコレクションはアンマネージリソースではないため、disposeメソッドではクリアされません。

2

usingはスコープを定義し、私たちが愛用しているDispose()の自動呼び出しを行います。

範囲外になる参照は、他のオブジェクトに参照がある場合はオブジェクト自体を「消える」ことはありません。この場合はcmd1を参照するparametersの場合が該当します。

2

cmd.Parameters.Clear()を追加する;実行後はうまくいくはずです。

0

パラメータオブジェクトのインスタンス化に失敗したため、この例外が発生しました。私は同じ名前のパラメータを持つ2つの手続きについて不平を言っていると思った。同じパラメータが2度追加されていると不平を言っていました。

  Dim aParm As New SqlParameter() 
      aParm.ParameterName = "NAR_ID" : aParm.Value = hfCurrentNAR_ID.Value 
      m_daNetworkAccess.UpdateCommand.Parameters.Add(aParm) 
      aParm = New SqlParameter 
      Dim tbxDriveFile As TextBox = gvNetworkFileAccess.Rows(index).FindControl("tbxDriveFolderFile") 
      aParm.ParameterName = "DriveFolderFile" : aParm.Value = tbxDriveFile.Text 
      m_daNetworkAccess.UpdateCommand.Parameters.Add(aParm) 
      **aParm = New SqlParameter()** <--This line was missing. 
      Dim aDDL As DropDownList = gvNetworkFileAccess.Rows(index).FindControl("ddlFileAccess") 
      aParm.ParameterName = "AccessGranted" : aParm.Value = aDDL.Text 
      **m_daNetworkAccess.UpdateCommand.Parameters.Add(aParm)** <-- The error occurred here. 
関連する問題