2009-08-01 7 views
1

データベースにデータを格納するためにクライアント側から呼び出されるWebサービスを作成しました。これらのデータは、1人のユーザーから200ミリ秒ごとに送信され、データが送信されるたびにデータベース接続が開かれ、閉じられます。これはパフォーマンスには悪いと思います。Webサービスからのデータベース処理 - パフォーマンスを向上させる方法

データがREST.StoreAcceleration()メソッドとSQLWorks.StoreAcceleration()は、次の方法を呼び出すことによって格納されます。

public Response StoreAcceleration(string strSessionString, string strMeasurementTime, string strAccelerationX, string strAccelerationY, string strAccelerationZ) 
    { 
     SQLWorks sqlWorks = new SQLWorks(); 
     Response response = new Response(); 
     try 
     { 
      string strTime = strMeasurementTime.Replace("_", " "); 
      DateTime measurementTime = DateTime.ParseExact(strTime, "yyyy-MM-dd HH:mm:ss:fff", null); 
      double accelerationX = Convert.ToDouble(strAccelerationX.Replace(".", ",")); 
      double accelerationY = Convert.ToDouble(strAccelerationY.Replace(".", ",")); 
      double accelerationZ = Convert.ToDouble(strAccelerationZ.Replace(".", ",")); 

      sqlWorks.StoreAcceleration(strSessionString, measurementTime, accelerationX, accelerationY, accelerationZ); 

      response.Successful = true; 
      response.Comment = "Stored!"; 
     } 
     catch(Exception ex) 
     { 
      string sDummy = ex.ToString(); 
      response.Comment = "an error occured!"; 
      response.Successful = false; 
     } 

     return response; 
    } 

public bool StoreAcceleration(string strStringSession, DateTime receivedTime, double accelerationX, double accelerationY, double accelerationZ) 
    { 
     bool result = false; 
     string select = 
      "INSERT INTO acceleration (session_id, measurement_time, acceleration_x, acceleration_y, acceleration_z) VALUES (@sessionID, @measurementTime, @accelerationX, @accelerationY, @accelerationZ)"; 
     SqlConnection conn = new SqlConnection(connectionString); 
     SqlCommand cmd = new SqlCommand(select, conn); 
     int sessionID = getSessionID(strStringSession); 
     if(sessionID == 0) 
      return false; 
     updateSessions(sessionID); 
     string strRecordTime = receivedTime.ToString("yyyy-MM-dd HH:mm:ss:fff"); 
     cmd.Parameters.AddWithValue("sessionID", sessionID.ToString()); 
     cmd.Parameters.AddWithValue("measurementTime", strRecordTime); 
     cmd.Parameters.AddWithValue("accelerationX", accelerationX.ToString()); 
     cmd.Parameters.AddWithValue("accelerationY", accelerationY.ToString()); 
     cmd.Parameters.AddWithValue("accelerationZ", accelerationZ.ToString()); 
     try 
     { 
      conn.Open(); 
      cmd.ExecuteNonQuery(); 
      result = true; 
     } 
     catch(Exception ex) 
     { 
      string sDummy = ex.ToString(); 
     } 
     finally 
     { 
      conn.Close(); 
     } 
     return result; 
    } 

ここでの問題は、SqlConnectionオブジェクトが開かれ、すべてのメソッド呼び出しに閉じていることです。

頻繁なデータベース接続の開閉を防ぐために、誰かが解決策を提案することができれば幸いです。

ありがとうございます!

+1

実際にパフォーマンスに問題がありますか、それともその最適化のためだけに最適化していますか? –

+0

パフォーマンスに問題がある場合は、データベースの側面を詳しく見ていきます。コードを少しきちんと整理したにもかかわらず、目立つほど速くはありません。 *接続プールが実際に無効にされていない限り。 – Thorarin

答えて

6

接続プールが設定されている場合、データベース接続はでなく、が閉じます。 conn.Close()は気にしないでください。 MSDNより:

Closeメソッドは、保留中のトランザクション をすべてロールバックします。接続プール への接続を から解放するか、または接続 プールが無効になっている場合は接続を閉じます。

あなたはすでにそれを使用していない場合は、それを設定するには、ここを参照してください: SQL Server connection pooling (ADO.NET)connection stringsを。

接続文字列にpooling=falseなどがある場合を除き、基本的にはアクティブであるはずです。ただし、使用する準備ができている2つの接続が常にあるように、MinPoolSizeを設定することをお勧めします。ところで


は、あなたが実際の文字列として受け取った時間を記憶していますか?そうでなければ、ToString(..)ものを取り除くことができます。 ADO.NETは、日付が誤って解釈されないようにします。実際には他の値も同様です。なぜあなたはそれらを文字列に変換していますか?

最後に、SqlCommandはIDisposableを実装しているため、接続と同様に処理する必要があります。私はこのようなものに書き換えることをお勧めしたい:

public bool StoreAcceleration(string strStringSession, DateTime receivedTime, double accelerationX, double accelerationY, double accelerationZ) 
{ 
    string select = 
     "INSERT INTO acceleration (session_id, measurement_time, acceleration_x, acceleration_y, acceleration_z) VALUES (@sessionID, @measurementTime, @accelerationX, @accelerationY, @accelerationZ)"; 

    int sessionID = getSessionID(strStringSession); 
    if (sessionID == 0) 
     return false; 
    updateSessions(sessionID); 

    using (SqlConnection conn = new SqlConnection(connectionString)) 
    using (SqlCommand cmd = new SqlCommand(select, conn)) 
    { 
     cmd.Parameters.AddWithValue("sessionID", sessionID); 
     cmd.Parameters.AddWithValue("measurementTime", receivedTime); 
     cmd.Parameters.AddWithValue("accelerationX", accelerationX); 
     cmd.Parameters.AddWithValue("accelerationY", accelerationY); 
     cmd.Parameters.AddWithValue("accelerationZ", accelerationZ); 

     try 
     { 
      conn.Open(); 
      cmd.ExecuteNonQuery(); 
      return true; 
     } 
     catch (Exception ex) 
     { 
      return false; 
     } 
    } 
} 

は、あなたは、もはやfinallyブロックでClose()コールを必要としません。変数connが範囲外になると、usingブロックは暗黙的にDispose()を呼び出します。それはClose()メソッドを内部的に呼び出します。

+0

+1の優れたアドバイス - 特に 'using'ステートメントの使用。あまりにも少数のADO.NETプログラマがそれを知って受け入れているようだ... –

0

デフォルトでは、接続プールが有効になっているので、データベース接続を再オープンすることは、私たちが思ったように高価ではありません。 Webサービスのリクエストごとに接続を開いたり閉じたりするのはまったく問題ありません。

関連する問題