1

多くのデータ処理を実行している Windows サービスがあります。ある時点で、サービスを閉じるときにサービスがクラッシュしましたSQLConnection。Close 接続メソッドの呼び出しにコメントすると、Service はクラッシュすることなく一貫して動作しています。

何が問題なのですか? 以下はコードスニペットです

private void DeleteTempTable()
    {
        _logger.Info("DeleteTempTable");

        try
        {

            foreach (KeyValuePair<string, string> item in _stables)
            {                 
                string dropSql = string.Empty;
                dropSql = string.Format("DROP TABLE [{0}];", item.Value);                 


                    SqlConnection oConnDropTables = new SqlConnection(connectionString);
                    oConnDropTables.Open();

                    if (!string.IsNullOrEmpty(dropSql))
                    {
                        using (SqlCommand cmd = new SqlCommand(dropSql, oConnDropTables))
                        {                              
                            cmd.ExecuteNonQuery();                             
                        }
                    }

              if (oConnDropTables != null && oConnDropTables.State == ConnectionState.Open)
                oConnDropTables.Close();                    
                oConnDropTables = null;



            }


        }
        catch (Exception ex)
        {
            _logger.Error("Error " + ex.Message);
            throw ex;
        }

    }

Close connection にコメントすると、サービスはクラッシュすることなく動作しています。また、catch ブロックにも引っかかりません。また、接続はなくNull、接続状態は開いているだけです..

私が試したこと: 1) 接続に「using」コンストラクトを配置する - 役に立たなかった 2) SQLException をキャッチして、得られるものがあるかどうかを確認する

4

2 に答える 2

2

それを削除しClose()ても問題が解決するわけではありません。率直に言って、問題が解決したとは思いません。あなたはまだ問題を理解していないので、ランダムなコード変更で問題が解決したと考えるのは時期尚早です。具体的には:

  • を使用するとClose()、毎回接続がプールに返されます。を呼び出すとOpen()、プールから同じ接続が返されます(いくつかの小さなことを除いて、クレンジングされます)
  • がないとClose()、前の接続がガベージ コレクションされたままになり、接続プールが飽和するか、データベース サーバーの接続数が飽和する可能性があります。基本的に - 悪いこと

私が考えているのは、ランダムなエラーが発生し、現在は表示されていないということです。たとえば、ネットワーク接続、または a の予測不可能な順序Dictionary<,>(つまり、テーブルがどの順序で ping されているかわからないことを意味します。テーブル間に外部キーがある場合DROP、これは非常に重要です)。

現在のコードの唯一の大きな問題は、 を使用していないことusingです。ただし、いくつかの冗長な行があります。これはより良いでしょう:

foreach (var item in _stables)
{                 
    var dropSql = string.Format("DROP TABLE [{0}];", item.Value);
    using(var oConnDropTables = new SqlConnection(connectionString))
    using (var cmd = new SqlCommand(dropSql, oConnDropTables))
    {
        oConnDropTables.Open();
        cmd.ExecuteNonQuery();
    }
}

または(望ましい):

using(var oConnDropTables = new SqlConnection(connectionString))
{
    oConnDropTables.Open();
    foreach (var item in _stables)
    {                 
        var dropSql = string.Format("DROP TABLE [{0}];", item.Value);
        using (var cmd = new SqlCommand(dropSql, oConnDropTables))
        {
            cmd.ExecuteNonQuery();
        }
    }
}
于 2013-01-02T11:53:13.117 に答える
0

問題は、ループが実行されるたびに新しい接続オブジェクトが作成されることです。SQL 接続を閉じると、実際には閉じられませんが、再利用できるようにアプリケーション プールに返されます。SQL で一度に開くことができる接続の数には制限があります。

SQLConnection オブジェクトをループの外に移動してみてください。ループ内でコマンドを実行し、ループが終了したら接続を閉じてください。

private void DeleteTempTable()
{
    _logger.Info("DeleteTempTable");

    try
    {
        using(SqlConnection oConnDropTables = new SqlConnection(connectionString))
        {
            oConnDropTables.Open();

            foreach (KeyValuePair<string, string> item in _stables)
            {                 
                string dropSql = string.Empty;
                dropSql = string.Format("DROP TABLE [{0}];", item.Value);                 

                if (!string.IsNullOrEmpty(dropSql))
                {
                    using (SqlCommand cmd = new SqlCommand(dropSql, oConnDropTables))
                    {                              
                        cmd.ExecuteNonQuery();                             
                    }
                }
            }
        }

    }
    catch (Exception ex)
    {
        _logger.Error("Error " + ex.Message);
        throw ex;
    }

}
于 2013-01-02T11:35:31.850 に答える