Quelle est la meilleure façon d'interroger des données à partir d'un serveur MS SQL en C #?
Je sais que ce n'est pas une bonne pratique d'avoir une requête SQL dans le code.
Est le meilleur moyen de créer une procédure stockée et de l'appeler à partir de C # avec des paramètres?
using (var conn = new SqlConnection(connStr))
using (var command = new SqlCommand("StoredProc", conn) { CommandType = CommandType.StoredProcedure }) {
conn.Open();
command.ExecuteNonQuery();
conn.Close();
}
L'utilisation de procédures stockées est un moyen et est largement utilisé depuis de nombreuses années.
Une façon plus moderne d'interagir avec les bases de données SQL Server à partir de C # (ou de tout langage .NET) consiste à utiliser Entity Framework. L'avantage d'Entity Framework est qu'il fournit un niveau d'abstraction plus élevé.
Pour citer Microsoft ( https://msdn.Microsoft.com/en-us/data/jj590134 ):
ADO.NET Entity Framework permet aux développeurs de créer des applications d'accès aux données en programmant avec un modèle d'application conceptuel au lieu de programmer directement avec un schéma de stockage relationnel. L'objectif est de réduire la quantité de code et de maintenance requise pour les applications orientées données. Les applications Entity Framework offrent les avantages suivants:
L'utilisation d'un ORM vs procédures stockées implique des compromis, en particulier en termes de sécurité et où réside la logique.
L'approche "classique" du développement avec SQL Server consiste à faire en sorte que la logique d'application réside dans les procédures stockées et les programmes ne disposant que des droits de sécurité pour exécuter les procédures stockées, et non pas à mettre à jour les tables directement. Le concept ici est que les procédures stockées sont la couche logique métier de la ou des applications. Bien que la théorie soit solide, elle a eu tendance à tomber en disgrâce pour diverses raisons, étant remplacée par la mise en œuvre de la logique métier dans un langage de programmation comme C # ou VB. Les bonnes applications sont toujours mises en œuvre avec une approche à plusieurs niveaux, y compris la séparation des préoccupations, etc., mais sont plus susceptibles de suivre un modèle comme MVC.
Un inconvénient de l'implémentation de la logique dans l'ORM plutôt que dans la base de données est la facilité de débogage et de test des règles d'intégrité des données par les responsables de la base de données (DA ou DBA). Prenons l'exemple classique du transfert d'argent de votre chèque vers votre compte d'épargne, il est important que cela se fasse comme une unité de travail atomique, en d'autres termes pris en sandwich dans une transaction. Si ce type de transfert ne peut être effectué que par le biais d'une procédure stockée, il est relativement facile pour le DA et les auditeurs d'AQ de la procédure stockée.
Si, d'autre part, cela se fait via un ORM comme Entity Framework et en production, on découvre que, dans de rares occasions, l'argent est retiré de la vérification mais non investi dans le débogage des économies peut être beaucoup plus complexe, en particulier si plusieurs programmes sont potentiellement impliqués. Ce serait très probablement un cas Edge, impliquant peut-être des problèmes matériels particuliers qui doivent se produire dans une séquence particulière, etc. Comment peut-on tester cela?
En fait, l'affirmation de base est discutable - il y a des compromis dans les deux sens entre avoir SQL dans le code ou avoir du code dans la base de données (c'est là que vous vous dirigez avec les procédures stockées).
Le résultat est qu'il n'y a pas de "meilleur" unique, ce n'est pas quelque chose que vous pouvez généraliser car quelle que soit la façon dont vous allez, vous faites un compromis (vous gagnez des avantages mais introduisez également des contraintes).
S'il existe une correspondance un à un entre votre application et votre base de données, cela n'a pas vraiment d'importance. Si, en revanche, vous disposez d'une grande base de données principale partagée par un nombre important d'applications, l'application de la cohérence au sein de la base de données entre ces applications devient beaucoup plus importante.
Ce qui est plus important, c'est de s'inquiéter de l'architecture et de la superposition de votre application - étant donné une couche d'accès aux données appropriée, que l'utilisation d'un ORM comme Entity Framework ou NHibernate ou faire quelque chose de plus direct devrait isoler la majeure partie de votre application de cette décision, que vous construisiez ou non des requêtes ou utiliser des procédures stockées.
Je serai libre d'avoir tendance à travailler sur des projets relativement petits avec de petites équipes (1 à 3 développeurs) - l'utilisation de procédures stockées est, pour moi, plus difficile que sa valeur car étant donné la nature de nos applications (et mes compétences?) Déployant de nouvelles le code est généralement beaucoup plus facile que la mise à jour du schéma (même si je dispose d'un code qui rend la mise à jour du schéma relativement simple) et je suis en mesure d'appliquer des règles métier en utilisant un code d'accès aux données commun. Il s'agit clairement d'un exemple classique de "Votre kilométrage peut varier".
Tant que vous avez paramétré vos entrées, toute approche est valide. La plupart des requêtes ne contenant pas d'arguments de code sont venues du mauvais vieux temps où de nombreuses bibliothèques vous ont forcé à ajouter vos instructions ensemble et c'est de là que proviennent les attaques par injection sql.
Les meilleures pratiques sont vraiment exagérées ici - il existe de nombreuses bonnes façons de le faire et celle que vous choisissez doit vraiment dépendre de ce qu'est votre application et de ce que vous devez faire. Cela dit, il n'y a que deux choses que vous pouvez vraiment faire de mal:
Comme le souligne @Bill, vous devez toujours paramétrer vos requêtes. La construction de chaînes est un vecteur facile pour l'injection SQL ainsi que toutes sortes de bogues difficiles à localiser. Des gens beaucoup plus intelligents ont compris comment tupéliser et échapper sql afin que vous n'ayez pas besoin de le découvrir vous-même.
Fermez vos connexions. La meilleure façon est de tout envelopper une instruction using, mais essayez/catch/enfin est cool aussi si cela fait flotter votre bateau. Mais assurez-vous toujours d'utiliser une connexion comme une voiture bon marché - conduisez-la durement et rapidement et supprimez-la rapidement.
L'autre pratique pour laquelle je plaiderais avec véhémence est que vous devez vous assurer de concentrer votre code d'accès aux données dans le moins d'endroits possible. Nous n'autorisons pas les applications Web frontales à contenir une référence directe à System.Data.SqlClient pour aider à appliquer cette mise en garde.