.NET Framework Meilleures pratiques - Exécution d'instructions SQL


Exemple

public void SaveNewEmployee(Employee newEmployee)
{
    // best practice - wrap all database connections in a using block so they are always closed & disposed even in the event of an Exception
    // best practice - retrieve the connection string by name from the app.config or web.config (depending on the application type) (note, this requires an assembly reference to System.configuration)
    using(SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionName"].ConnectionString))
    {
        // best practice - use column names in your INSERT statement so you are not dependent on the sql schema column order
        // best practice - always use parameters to avoid sql injection attacks and errors if malformed text is used like including a single quote which is the sql equivalent of escaping or starting a string (varchar/nvarchar)
        // best practice - give your parameters meaningful names just like you do variables in your code
        using(SqlCommand sc = new SqlCommand("INSERT INTO employee (FirstName, LastName, DateOfBirth /*etc*/) VALUES (@firstName, @lastName, @dateOfBirth /*etc*/)", con))
        {
            // best practice - always specify the database data type of the column you are using
            // best practice - check for valid values in your code and/or use a database constraint, if inserting NULL then use System.DbNull.Value
            sc.Parameters.Add(new SqlParameter("@firstName", SqlDbType.VarChar, 200){Value = newEmployee.FirstName ?? (object) System.DBNull.Value});
            sc.Parameters.Add(new SqlParameter("@lastName", SqlDbType.VarChar, 200){Value = newEmployee.LastName ?? (object) System.DBNull.Value});

            // best practice - always use the correct types when specifying your parameters, Value is assigned to a DateTime instance and not a string representation of a Date
            sc.Parameters.Add(new SqlParameter("@dateOfBirth", SqlDbType.Date){ Value = newEmployee.DateOfBirth });

            // best practice - open your connection as late as possible unless you need to verify that the database connection is valid and wont fail and the proceeding code execution takes a long time (not the case here)
            con.Open();
            sc.ExecuteNonQuery();
        }

        // the end of the using block will close and dispose the SqlConnection
        // best practice - end the using block as soon as possible to release the database connection
    }
}

// supporting class used as parameter for example
public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

Meilleure pratique pour travailler avec ADO.NET

  • La règle de base est d'ouvrir la connexion pour un minimum de temps. Fermez la connexion explicitement une fois l'exécution de votre procédure terminée, cela renverra l'objet de connexion au pool de connexions. Taille maximale du pool de connexion par défaut = 100. Le regroupement de connexions améliore les performances de la connexion physique à SQL Server. Regroupement de connexions dans SQL Server
  • Enveloppez toutes les connexions de base de données dans un bloc using afin qu'elles soient toujours fermées et éliminées même en cas d'exception. Voir l' utilisation de Statement (C # Reference) pour plus d'informations sur l'utilisation des instructions
  • Récupère les chaînes de connexion par nom depuis app.config ou web.config (selon le type d'application)
  • Toujours utiliser les paramètres pour les valeurs entrantes pour
    • Eviter les attaques par injection SQL
    • Évitez les erreurs si du texte mal formé est utilisé, y compris un guillemet simple qui équivaut à SQL pour échapper ou démarrer une chaîne (varchar / nvarchar)
    • Permettre au fournisseur de base de données de réutiliser les plans de requête (non pris en charge par tous les fournisseurs de bases de données), ce qui augmente l'efficacité
  • Lorsque vous travaillez avec des paramètres
    • Le type de paramètres SQL et la non-concordance de taille sont une cause fréquente d'échec d'insertion / mise à jour / sélection
    • Donnez des noms significatifs à vos paramètres SQL, tout comme vous faites des variables dans votre code
    • Indiquez le type de données de base de données de la colonne que vous utilisez, cela garantit que les types de paramètres incorrects ne sont pas utilisés, ce qui pourrait entraîner des résultats inattendus
    • Validez vos paramètres entrants avant de les transmettre à la commande (comme dit le proverbe, " garbage in, garbage out "). Valider les valeurs entrantes le plus tôt possible dans la pile
    • Utilisez les types corrects lors de l'attribution de vos valeurs de paramètre, par exemple: n'affectez pas la valeur de chaîne d'un DateTime, mais assignez une instance DateTime réelle à la valeur du paramètre
    • Spécifiez la taille des paramètres de type chaîne. Cela est dû au fait que SQL Server peut réutiliser les plans d'exécution si le type et la taille des paramètres correspondent. Utilisez -1 pour MAX
    • N'utilisez pas la méthode AddWithValue , la raison principale est qu'il est très facile d'oublier de spécifier le type de paramètre ou la précision / l'échelle si nécessaire. Pour plus d'informations, voir Peut-on arrêter d'utiliser AddWithValue déjà?
  • Lors de l'utilisation de connexions de base de données
    • Ouvrez la connexion le plus tard possible et fermez-la dès que possible. Ceci est une directive générale lorsque vous travaillez avec une ressource externe
    • Ne partagez jamais les instances de connexion à la base de données (exemple: le fait qu'un singleton héberge une instance partagée de type SqlConnection ). Demandez à votre code de toujours créer une nouvelle instance de connexion à la base de données en cas de besoin, puis de supprimer le code d'appel et de le «jeter» lorsqu'il est terminé. La raison en est
      • La plupart des fournisseurs de bases de données disposent d'une sorte de pool de connexions, ce qui fait que la création de nouvelles connexions gérées est peu coûteuse.
      • Il élimine les erreurs futures si le code commence à fonctionner avec plusieurs threads