2009-08-01 8 views
1

J'ai créé un service Web qui est appelé du côté client pour stocker les données dans la base de données. Ces données sont envoyées toutes les 200 ms par un seul utilisateur et chaque fois que les données sont envoyées, la connexion à la base de données est ouverte et fermée ce qui, à mon avis, n'est pas bon pour la performance.Gestion de base de données à partir du service Web - comment améliorer les performances?

Les données sont stockées en appelant la méthode REST.StoreAcceleration() et SQLWorks.StoreAcceleration() de la manière suivante:

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; 
    } 

Le problème ici est que SqlConnection est ouvert et fermé à chaque appel de méthode.

J'apprécierais que quelqu'un puisse suggérer comment améliorer la solution afin d'empêcher l'ouverture/la fermeture fréquente de la base de données.

Merci!

+1

Avez-vous réellement un problème de performance, ou optimisez-vous simplement pour le plaisir? –

+0

S'il y a un problème de performance, je regarderais de plus près la base de données. Même si j'ai nettoyé un peu le code, ça ne sera pas beaucoup plus rapide. * À moins que * la mise en commun des connexions ait été désactivée, bien sûr. – Thorarin

Répondre

6

Si vous avez configuré un pool de connexions, votre connexion à la base de données se fermera et non. Peu importe le conn.Close(). À partir de MSDN:

La méthode Close annule toutes les transactions en attente . Il libère ensuite la connexion au pool de connexions, ou ferme la connexion si la connexion est désactivée.

Voir ici pour le configurer, si vous n'êtes pas déjà l'utiliser: SQL Server connection pooling (ADO.NET) et connection strings. Fondamentalement, sauf si vous avez pooling=false ou quelque chose de similaire dans votre chaîne de connexion, il devrait déjà être actif. Cependant, vous pouvez configurer MinPoolSize pour avoir toujours quelques connexions prêtes à être utilisées. Par ailleurs, stockez-vous l'heure reçue en tant que chaînes réelles? Sinon, vous pouvez vous débarrasser de toute la chose ToString(..). ADO.NET s'assurera que la date ne soit pas mal interprétée. La même chose vaut pour les autres valeurs vraiment; pourquoi les convertis-tu en ficelles?

Enfin, SqlCommand implémente IDisposable, vous devriez donc l'éliminer, un peu comme la connexion. Je vous suggère de réécrire quelque chose comme ceci:

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; 
     } 
    } 
} 

Plus besoin de l'appel Close() dans un bloc finally. Le bloc using appellera implicitement Dispose() lorsque la variable conn sort du champ d'application. Cela appellera à son tour la méthode Close() en interne.

+0

+1 excellent conseil - en particulier sur l'utilisation des instructions 'using'. Bien trop peu de programmeurs ADO.NET semble savoir et embrasser cela ... –

0

Par défaut, le regroupement de connexions est activé, donc rouvrir une connexion à une base de données n'est pas si cher que nous le pensions. Il est parfaitement possible d'ouvrir et de fermer la connexion pour chaque demande de service Web.

Questions connexes