2

C# で記述されたコマンド ライン ユーティリティがあります。これは、データベース内のいくつかのレコードを更新してから、他のものをチェックするループに入ります。何らかの理由で、SQL の実行後、SQL Server 2008 で待機中のコマンド セッションが常にスリープ状態のままになります。SQL サーバー アクティビティ モニターを使用し、sp_who2 を実行してそれを確認できます。しかし、SQL トランザクションは確かに正常にコミットされました。これは、コードのデバッグと、データベース内のデータ レコードのタイムスタンプからわかります。また、コマンドライン ユーティリティを明示的に停止すると、開いているスリープ セッションが強制終了されます。これは、私の関数が、アプリケーションが中止されたときに CLR によってガベージ コレクションされるまで破棄できない SQL 接続オブジェクトを作成することを示しているようです。これはどのように起こりますか?ありがとう。コードは次のとおりです。

bool result = false;
     using (SqlConnection conn = new SqlConnection(this.Connection))
     {

        using (SqlCommand cmd = conn.CreateCommand())
        {
           cmd.CommandText =
                 @"if not exists (select id from pl where sj=@sj and ej=@ej and dateInactivated is null) 
                       insert into pl(sj,ej,pf, br, tk, lastModified )
                       values(@sj,@ej,@pf,@br,@tk,getDate())
                    else
                       update pl set sj=@sj,ej=@ej,pf=@pf,br=@br,tk=@tk,lastModified=getDate()
                       where sj=@sj and ej=@ej and dateInactivated is null
                    ";

           cmd.Parameters.AddWithValue("@sj", sj);
           cmd.Parameters.AddWithValue("@ej", ej);
           cmd.Parameters.AddWithValue("@pf", pf);
           cmd.Parameters.AddWithValue("@br", br);
           cmd.Parameters.AddWithValue("@tk", tkData);
           cmd.CommandTimeout = 60;
           SqlTransaction trans = null;
           try
           {
              conn.Open();
              trans = conn.BeginTransaction();
              cmd.Transaction = trans;
              cmd.ExecuteNonQuery();
              trans.Commit();
              conn.Close();
              result = true;
           }
           catch (SqlException ex)
           {
              if (trans != null)
              {
                 trans.Rollback();
              }
              Log.WriteLog(LogLevel.ERROR, ex.Message);
              result = false;
           }
           finally
           {
              if (conn.State != ConnectionState.Closed)
              {
                 conn.Close();
              }
           }
        }

     }

     return result;

tk フィールドは xml データベース フィールドであることに注意してください。

4

2 に答える 2

8

これは接続プーリングと呼ばれ、このように動作させたいと考えています

基本的に、接続を完全に切断してアプリ用に再確立すると、以前のコードの呼び出しから取り残されたアイドル状態の接続を再利用するよりもはるかに高いペナルティが発生します。これは良いことです。

于 2012-08-28T17:57:12.490 に答える
3

プーリングによるものです。99.99% の確率で、これは素晴らしいことです。これにより、作成および切断される接続が少なくなり、マルチスレッド化によって同時に開かれる接続が少なくなります。

接続文字列に追加Pooling=falseすると、使用されません。これを行う唯一の理由は次のとおりです。

  1. プールされた接続をどこかに漏らしている場合の一時的な手段として - これはパフォーマンスに関する限り悪い状況を悪化させますが、最大プールサイズには達しないことに注意してください。ここでは一時的なことに重点を置いています。
  2. データベースを共有するクライアント アプリケーションがあり、非常に短い時間だけ接続を使用します。ここでは、各クライアントの効率が低下しますが、サーバー自体の負荷が軽減されるため、プーリングをオフにします。

2番目は非常にまれです。最初のものは非常にまれである必要があります - 繰り返しますが、一時的なものに重点を置いてください。

于 2012-08-28T18:07:50.657 に答える