2009-05-26 10 views
6

Quelle est la meilleure pratique pour les connexions SQL?Gestion des connexions SQL Server

Actuellement, je suis en utilisant les éléments suivants:

using (SqlConnection sqlConn = new SqlConnection(CONNECTIONSTRING)) 
{ 
    sqlConn.Open(); 
    // DB CODE GOES HERE 
} 

J'ai lu que c'est un moyen très efficace de faire des connexions SQL. Par défaut, le regroupement SQL est actif, alors comment je comprends que lorsque le code using se termine, l'objet SqlConnection est fermé et supprimé, mais la connexion réelle à la base de données est placée dans le pool de connexions SQL. Ai-je tort à ce sujet?

Répondre

13

C'est tout. Quelques points supplémentaires à considérer:

  • Où obtenez-vous votre chaîne de connexion? Vous ne voulez pas que cela soit codé de toutes pièces et vous devrez peut-être le sécuriser.
  • Vous avez souvent d'autres objets pour créer aussi bien avant vraiment utiliser la connexion (SqlCommand, SqlParameter, DataSet, SqlDataAdapter), et vous voulez attendre aussi longtemps que possible pour ouvrir la connexion. Le modèle complet doit en tenir compte.
  • Vous voulez vous assurer que l'accès à votre base de données est forcé dans sa propre classe ou ensemble de couches de données. Donc, une chose courante à faire est d'exprimer cela comme un appel de fonction privée:

.

private static string connectionString = "load from encrypted config file"; 
private SqlConnection getConnection() 
{ 
    return new SqlConnection(connectionString); 
} 

Et puis rédigez votre échantillon comme ceci:

using (SqlConnection sqlConn = getConnection()) 
{ 
    // create command and add parameters 

    // open the connection 
    sqlConn.Open(); 

    // run the command 
} 

Cet échantillon ne peut exister que dans votre classe d'accès aux données. Une alternative consiste à marquer internal et à répartir la couche de données sur un ensemble complet. La chose principale est qu'une séparation propre de votre code de base de données est strictement appliquée.

Une véritable mise en œuvre pourrait ressembler à ceci:

public IEnumerable<IDataRecord> GetSomeData(string filter) 
{ 
    string sql = "SELECT * FROM [SomeTable] WHERE [SomeColumn] LIKE @Filter + '%'"; 

    using (SqlConnection cn = getConnection()) 
    using (SqlCommand cmd = new SqlCommand(sql, cn)) 
    { 
     cmd.Parameters.Add("@Filter", SqlDbType.NVarChar, 255).Value = filter; 
     cn.Open(); 

     using (IDataReader rdr = cmd.ExecuteReader()) 
     { 
      while (rdr.Read()) 
      { 
       yield return (IDataRecord)rdr; 
      } 
     } 
    } 
} 

Notez que j'ai pu « pile » la création des objets cn et cmd, et réduire ainsi l'imbrication et seulement créer un bloc de portée. Enfin, un mot d'avertissement à propos de l'utilisation du code yield return dans cet exemple spécifique. Si vous appelez la méthode et ne complétez pas votre DataBinding ou toute autre utilisation tout de suite, il pourrait maintenir la connexion ouverte pendant une longue période. Un exemple de ceci est l'utiliser pour définir une source de données dans l'événement Load d'une page ASP.NET. Étant donné que l'événement de liaison de données réel ne se produira pas plus tard, vous pouvez maintenir la connexion ouverte beaucoup plus longtemps que nécessaire.

+0

point 1: Je stocke mes chaînes de connexion dans la section de l'app/web.config Point 2: Est-ce quelque chose dont je devrais m'inquiéter? Je fais normalement SqlConnection, puis je l'ouvre, puis je crée ma commande sqlCommand, puis je prends de là. Point 3: Nous faisons tous nos accès DB à partir d'une classe lib. Je n'aime pas faire l'accès DB forme l'application de base. Cela vaut-il la peine de créer la méthode getConnection? – Neale

+0

Étant donné que vous utilisez un accès à la bibliothèque lib pour tous les db, il est très simple de faire en sorte que la chaîne de connexion fasse partie du fichier .config de la classe lib plutôt que du fichier .config global de l'application. Cela devrait être assez bon pour imposer une séparation de couche de données propre, mais en même temps il n'y a aucune raison de rendre la méthode publique non plus. Cela devrait concerner les points 1 et 3. Pour le point 2, cela ne blesse probablement rien de l'ouvrir pour une ou deux lignes supplémentaires, mais cela n'aide pas non plus. Je suis en train d'éditer pour une autre raison, vous pourriez vouloir le faire de cette façon. –

+0

Votre exemple de retour de rendement est légèrement trompeur. Une fonction construite autour de 'yield return' ne démarre pas executig avant le premier appel de' MoveNext() 'sur' IEnumerator'. Ainsi, même si vous appelez la fonction, la connexion ne sera pas ouverte tant que vous n'aurez pas recommencé à parcourir les résultats. –

1

Votre compréhension de l'utilisation est correcte, et cette méthode d'utilisation est recommandée. Vous pouvez également appeler close dans votre code.

+1

Merci. La façon dont je le comprends quand le "using" est fini et qui appelle SqlConnection.Dispose(); que ultimatly appelle SqlConnection.Close() – Neale

+0

votre compréhension de "using" est également correcte. –

+0

@Neale - Oui, SqlConnection.Dispose() appellera Close si nécessaire. Si la connexion était déjà fermée, elle renvoie simplement le handle au fournisseur ado.net, qui est alors libre de le mettre dans un pool ou de le fermer. –

2

Les bibliothèques Patterns and Practices de Microsoft constituent une excellente approche pour la gestion de la connectivité de base de données. Les bibliothèques encapsulent la plupart des mécanismes impliqués dans l'ouverture d'une connexion, ce qui vous facilitera la vie.

0

Aussi: Ouvert tard, ferme tôt.N'ouvrez pas la connexion tant qu'il ne reste plus aucune étape avant d'appeler la base de données.

Et fermez la connexion dès que vous avez terminé.

Questions connexes