web-dev-qa-db-fra.com

Création de connexions à la base de données - Faites-le une fois ou pour chaque requête?

Pour le moment, je crée une connexion à la base de données lors du premier chargement de ma page Web. Je traite ensuite la page et exécute toutes les requêtes contre cette connexion. Est-ce la meilleure façon de le faire ou dois-je créer une connexion à une base de données chaque fois que j'exécute une requête?

p.s Il est plus logique pour moi de créer une connexion et de l'utiliser, mais je ne sais pas si cela peut provoquer d'autres problèmes.

J'utilise C # (ASP.NET) avec MSSQL.

119
webnoob

Si vous en créez une par requête/transaction, il est beaucoup plus facile de gérer la "fermeture" des connexions.

Je peux voir pourquoi le bon sens dicte que vous devez en ouvrir un et l'utiliser tout au long, mais vous rencontrerez des problèmes avec les connexions interrompues et le multithreading. Votre prochaine étape consistera donc à ouvrir un pool, disons 50 connexions, et à les garder toutes ouvertes, en les distribuant à différents processus. Et puis vous découvrirez que c'est exactement ce que le framework .NET fait déjà pour vous .

Si vous ouvrez une connexion lorsque vous en avez besoin et la supprimez lorsque vous avez terminé, cela ne fermera pas réellement la connexion, elle la renverra simplement dans le pool de connexions pour être réutilisée.

139
pdr

Il est préférable de créer une connexion par requête - et dans le cas de l'affichage de données, la meilleure pratique consiste à faire en sorte que la requête apporte toutes les données nécessaires dans un coup.

Informations générales:

Dans .NET, l'appel de SqlConnection.Open() utilise par défaut toujours de manière transparente pool de connexions (voir "Utilisation du pool de connexions avec SQL Server" sur MSDN). Ainsi, vous pouvez simplement saisir une nouvelle connexion en utilisant Open(), et appeler Close() lorsque vous avez terminé, et .NET fera la bonne chose.

Notez que sans regroupement de connexions, une connexion par requête serait une très mauvaise idée car la création de véritables connexions à la base de données peut être très coûteuse (authentification, surcharge réseau, etc.), et le nombre de connexions ouvertes simultanées est généralement très limité.

39
Oded

Les développeurs souhaitent parfois "optimiser" leur code pour réutiliser leurs objets de connexion. Étant donné le contexte de cette question nous place dans l'écosystème .Net, c'est presque toujours une erreur. (Remarque: de nombreuses autres plates-formes gèrent également cela de manière similaire).

ADO.Net a une fonctionnalité appelée Pooling de connexions . Lorsque vous créez et ouvrez un nouvel objet de connexion, ce que vous faites réellement, c'est de demander une connexion à un pool. Lorsque vous fermez une connexion, vous la renvoyez au pool.

Il est important de comprendre les objets que nous utilisons directement dans le code: SqlConnection, MySqlConnection, OleDbConnection, etc., sont tous juste - wrappers autour d'une véritable connexion sous-jacente gérée par ADO.Net et ADO.Net real les connexions sont beaucoup plus "lourdes" et plus chères du point de vue des performances. Ce sont ces objets sous-jacents qui ont des soucis comme l'authentification, le transit réseau, le chiffrement, etc., et ces choses dépassent de loin la petite quantité de mémoire dans l'objet que vous voyez réellement dans votre propre code.

Lorsque vous essayez de réutiliser votre objet de connexion, vous gagnez en efficacité dans la petite chose au détriment de la chose beaucoup plus grande, parce que vous brisez la capacité pour ADO.Net pour gérer efficacement les importantes connexions sous-jacentes.

La réutilisation d'une connexion sur une application ou une requête http peut également vous forcer à sérialiser accidentellement quelque chose qui pourrait autrement s'exécuter en parallèle et devenir un goulot d'étranglement des performances. J'ai vu cela se produire dans de vraies applications.

Dans le cas de l'exemple de page Web ici, où vous ne conservez au moins que la petite connexion pendant la durée d'une seule demande/réponse http, vous pouvez gagner encore plus d'efficacité en évaluant les requêtes que vous exécutez dans votre pipeline de demandes et essayez d'obtenir les réduire à autant de requêtes distinctes que possible dans la base de données (indice: vous pouvez soumettre plusieurs requêtes dans une même chaîne SQL et utiliser DataReader.NextResult() ou vérifier différentes tables dans un DataSet pour se déplacer entre eux).

En d'autres termes, plutôt que de penser en termes de réutilisation d'une connexion pour une application ou d'une requête http par rapport à une connexion par requête, pensez en termes d'une connexion pour chaque fois que vous appelez à la base de données ... à chaque aller-retour. Essayez ensuite de minimiser le nombre de connexions en minimisant le nombre de ces trajets. De cette façon, vous pouvez satisfaire les deux objectifs.


Mais ce n'est qu'un type d'optimisation. Il y a aussi l'optimisation du temps du programmeur et la réutilisation efficace du code. Les développeurs ne veulent pas écrire le même code passe-partout encore et encore juste pour obtenir un objet de connexion ouvert et prêt à l'emploi. Ce n'est pas seulement fastidieux, c'est un moyen d'introduire des bugs dans un programme.

Même ici, cependant, il est généralement préférable d'avoir une connexion par requête (ou aller-retour). Il existe des modèles que vous pouvez utiliser pour éviter de réécrire le même code passe-partout, tout en conservant l'objectif d'une connexion par appel à la base de données. Voici un exemple J'aime, mais il y en a beaucoup d'autres.

2
Joel Coehoorn