Valider des données dans des jeux de données dans les applications .NET Framework

Remarque

Les jeux de données et les classes associées sont des technologies .NET Framework héritées qui datent du début des années 2000. Elles permettent aux applications d’utiliser des données en mémoire pendant que les applications sont déconnectées de la base de données. Elles sont particulièrement utiles aux applications qui permettent aux utilisateurs de modifier des données, et de rendre ces changements persistants dans la base de données. Même si les jeux de données sont une technologie très efficace, nous vous recommandons d’utiliser Entity Framework Core pour les nouvelles applications .NET. Entity Framework offre un moyen plus naturel d’utiliser des données tabulaires en tant que modèles objet. De plus, il présente une interface de programmation plus simple.

La validation des données est le processus qui consiste à confirmer que les valeurs entrées dans les objets de données sont conformes aux contraintes du schéma d’un jeu de données. Le processus de validation contrôle également que ces valeurs suivent les règles établies pour l’application. Il est recommandé de valider les données avant d’envoyer des mises à jour à la base de données sous-jacente. Cela permet de limiter les erreurs et de réduire le nombre potentiel d’allers-retours entre une application et la base de données.

Pour vous assurer que les données écrites dans un jeu de données sont valides, vous pouvez créer des vérifications de validation dans le jeu de données proprement dit. Le jeu de données peut vérifier les données quelle que soit la façon dont la mise à jour est effectuée, que ce soit directement par des contrôles dans un formulaire, au sein d’un composant ou d’une autre manière. Étant donné que le jeu de données fait partie de l’application (contrairement au back-end de base de données), il s’agit d’un emplacement logique pour générer une validation propre à l’application.

Le meilleur endroit pour ajouter une validation à l’application est le fichier de classe partiel du jeu de données. Dans Visual Basic ou Visual C#, ouvrez le Concepteur de DataSet et double-cliquez sur la colonne ou la table pour laquelle vous souhaitez créer la validation. Cette action a pour effet d’ouvrir le fichier de code, dans lequel vous pouvez créer un gestionnaire d’événements ColumnChanging ou RowChanging.

private static void OnColumnChanging(object sender, DataColumnChangeEventArgs e)
{

}

Valider des données

La validation dans un jeu de données s’effectue de différentes manières :

Plusieurs événements sont déclenchés par l’objet DataTable lorsqu’une modification se produit dans un enregistrement :

  • Les événements ColumnChanging et ColumnChanged sont déclenchés pendant et après chaque modification de colonne. L’événement ColumnChanging est utile lorsque vous souhaitez valider des modifications dans des colonnes spécifiques. Les informations sur la modification proposée sont passées en argument de l’événement.
  • Les événements RowChanging et RowChanged sont déclenchés pendant et après chaque modification de ligne. L’événement RowChanging est plus général. Il indique qu’une modification se produit quelque part dans la ligne, sans préciser quelle colonne a changé.

Par défaut, chaque modification apportée à une colonne déclenche donc quatre événements. En premier viennent les événements ColumnChanging et ColumnChanged pour la colonne spécifique en cours de modification. Ils sont suivis des événements RowChanging et RowChanged. Si plusieurs modifications sont apportées à la ligne, les événements sont déclenchés pour chacune d’elles.

Notes

La méthode BeginEdit de la ligne de données désactive les événements RowChanging et RowChanged après chaque modification de colonne. Dans ce cas, l’événement n’est pas déclenché tant que la méthode EndEdit n’a pas été appelée, lorsque les événements RowChanging et RowChanged ne sont déclenchés qu’une seule fois. Pour plus d’informations, consultez Désactivation des contraintes lors du remplissage d’un jeu de données.

L’événement à choisir dépend de la précision de la validation. S’il est important que vous puissiez intercepter immédiatement une erreur lorsqu’une colonne change, générez la validation à l’aide de l’événement ColumnChanging. Sinon, utilisez l’événement RowChanging, ce qui peut entraîner le rattrapage de plusieurs erreurs à la fois. Si vos données sont structurées de sorte que la valeur d’une colonne est validée en fonction du contenu d’une autre colonne, effectuez votre validation pendant l’événement RowChanging.

Lorsque les enregistrements sont mis à jour, l’objet DataTable déclenche des événements auxquels vous pouvez répondre à mesure que des modifications se produisent et après qu’elles ont été apportées.

Si votre application utilise un jeu de données typé, vous pouvez créer des gestionnaires d’événements fortement typés. Cela ajoute quatre événements typés supplémentaires pour lesquels vous pouvez créer des gestionnaires : dataTableNameRowChanging, dataTableNameRowChanged, dataTableNameRowDeleting et dataTableNameRowDeleted. Ces gestionnaires d’événements typés passent un argument comprenant les noms de colonnes de la table, ce qui facilite l’écriture et la lecture du code.

Événements de mise à jour des données

Événement Description
ColumnChanging La valeur d’une colonne est en cours de modification. L’événement vous transmet la ligne et la colonne, ainsi que la nouvelle valeur proposée.
ColumnChanged La valeur d’une colonne a été modifiée. L’événement vous transmet la ligne et la colonne, ainsi que la valeur proposée.
RowChanging Les modifications apportées à un objet DataRow sont sur le point d’être validées dans le jeu de données. Si vous n’avez pas appelé la méthode BeginEdit, l’événement RowChanging est déclenché pour chaque modification de colonne juste après que l’événement ColumnChanging a été déclenché. Si vous avez appelé BeginEdit avant d’effectuer les modifications, l’événement RowChanging n’est déclenché que lorsque vous appelez la méthode EndEdit.

L’événement vous transmet la ligne, ainsi qu’une valeur indiquant le type d’action (modification, insertion, etc.) en cours d’exécution.
RowChanged Une ligne a été modifiée. L’événement vous transmet la ligne, ainsi qu’une valeur indiquant le type d’action (modification, insertion, etc.) en cours d’exécution.
RowDeleting Une ligne est en cours de suppression. L’événement vous transmet la ligne, ainsi qu’une valeur indiquant le type d’action (suppression) en cours d’exécution.
RowDeleted Une ligne a été supprimée. L’événement vous transmet la ligne, ainsi qu’une valeur indiquant le type d’action (suppression) en cours d’exécution.

Les événements ColumnChanging, RowChanging et RowDeleting sont déclenchés pendant le processus de mise à jour. Vous pouvez les utiliser pour valider des données ou effectuer d’autres types de traitement. Étant donné que la mise à jour est en cours pendant ces événements, vous avez la possibilité de l’annuler en lançant une exception, qui empêche la mise à jour de se terminer.

Les événements ColumnChanged, RowChanged et RowDeleted sont des événements de notification déclenchés lorsque la mise à jour a réussi. Ils sont utiles pour effectuer d’autres actions qui dépendent de cette réussite.

Validation des données au cours des modifications de colonnes

Notes

Le Concepteur de DataSet crée une classe partielle dans laquelle la logique de validation peut être ajoutée à un jeu de données. Le jeu de données généré par le Concepteur ne supprime ni ne modifie le code de la classe partielle.

Vous pouvez valider des données lorsque la valeur d’une colonne de données change en répondant à l’événement ColumnChanging. Lorsqu’il est déclenché, cet événement passe un argument d’événement (ProposedValue) qui contient la valeur proposée pour la colonne active. En fonction du contenu de e.ProposedValue, vous pouvez effectuer les actions suivantes :

  • Acceptez la valeur proposée sans rien faire.

  • Rejetez la valeur proposée en définissant l’erreur de colonne (SetColumnError) dans le gestionnaire d’événements de modification de colonne.

  • Si vous le souhaitez, utilisez un contrôle ErrorProvider pour afficher un message d’erreur à l’utilisateur. Pour plus d’informations, consultez ErrorProvider, composant.

La validation peut également être effectuée pendant l’événement RowChanging.

Validation des données au cours des modifications de lignes

Vous pouvez écrire du code permettant de vérifier que chaque colonne à valider contient des données qui répondent aux exigences de votre application. Pour ce faire, définissez la colonne de façon à indiquer qu’elle contient une erreur si une valeur proposée est inacceptable. Les exemples suivants prévoient une erreur de colonne lorsque la colonne Quantity est inférieure ou égal à 0. Les gestionnaires d’événements de modification de ligne se présentent comme dans les exemples suivants.

Validation des données lorsqu’une ligne change (Visual Basic)

  1. Ouvrez votre dataset dans le Concepteur de DataSet. Pour plus d’informations, consultez Procédure pas à pas : Création d’un jeu de données dans le Concepteur de DataSet.

  2. Double-cliquez sur la barre de titre de la table à valider. Cette action a pour effet de créer automatiquement le gestionnaire d’événements RowChanging de la DataTable dans le fichier de classe partielle du jeu de données.

    Conseil

    Double-cliquez à gauche du nom de la table pour créer le gestionnaire d’événements de modification de ligne. Vous pouvez modifier le nom de la table en double-cliquant dessus.

    Private Sub Order_DetailsDataTable_Order_DetailsRowChanging(
        ByVal sender As System.Object, 
        ByVal e As Order_DetailsRowChangeEvent
      ) Handles Me.Order_DetailsRowChanging
    
        If CType(e.Row.Quantity, Short) <= 0 Then
            e.Row.SetColumnError("Quantity", "Quantity must be greater than 0")
        Else
            e.Row.SetColumnError("Quantity", "")
        End If
    End Sub
    

Validation des données lorsqu’une ligne change (C#)

  1. Ouvrez votre dataset dans le Concepteur de DataSet. Pour plus d’informations, consultez Procédure pas à pas : Création d’un jeu de données dans le Concepteur de DataSet.

  2. Double-cliquez sur la barre de titre de la table à valider. Cette action a pour effet de créer un fichier de classe partielle pour la DataTable.

    Notes

    Le Concepteur de DataSet ne crée pas automatiquement de gestionnaire d’événements pour l’événement RowChanging. Vous devez définir une méthode permettant de gérer l’événement et exécuter du code RowChanging pour connecter l’événement dans la méthode d’initialisation de la table.

  3. Copiez le code suivant dans la classe partielle :

    public override void EndInit()
    {
        base.EndInit();
        Order_DetailsRowChanging += TestRowChangeEvent;
    }
    
    public void TestRowChangeEvent(object sender, Order_DetailsRowChangeEvent e)
    {
        if ((short)e.Row.Quantity <= 0)
        {
            e.Row.SetColumnError("Quantity", "Quantity must be greater than 0");
        }
        else
        {
            e.Row.SetColumnError("Quantity", "");
        }
    }
    

Récupération des lignes modifiées

Chaque ligne d’une table de données possède une propriété RowState qui effectue le suivi de l’état actuel de la ligne à l’aide des valeurs de l’énumération DataRowState. Pour retourner des lignes modifiées d’un jeu de données ou d’une table de données, appelez la méthode GetChanges d’un DataSet ou d’une DataTable. Vous pouvez vérifier la présence de modifications avant d’appeler GetChanges en appelant la méthode HasChanges d’un jeu de données.

Notes

Une fois les modifications d’un jeu de données ou d’une table de données validées (en appelant la méthode AcceptChanges), la méthode GetChanges ne retourne aucune donnée. Si votre application doit traiter les lignes modifiées, vous devez le faire avant d’appeler la méthode AcceptChanges.

La méthode GetChanges d’un jeu de données ou d’une table de données retourne un nouveau jeu de données ou une nouvelle table de données ne contenant que les enregistrements modifiés. Si vous souhaitez obtenir des enregistrements spécifiques (par exemple uniquement les nouveaux enregistrements ou uniquement les enregistrements modifiés), vous pouvez passer une valeur de l’énumération DataRowState en paramètre de la méthode GetChanges.

Utilisez l’énumération DataRowVersion pour accéder aux différentes versions d’une ligne (par exemple les valeurs d’origine qui se trouvaient dans une ligne avant son traitement).

Récupération de tous les enregistrements modifiés d’un jeu de données

  • Appelez la méthode GetChanges d’un jeu de données.

    L’exemple suivant crée un jeu de données nommé changedRecords et le remplit avec tous les enregistrements modifiés d’un autre jeu de données nommé dataSet1.

    DataSet changedRecords = dataSet1.GetChanges();
    

Récupération de tous les enregistrements modifiés d’une table de données

  • Appelez la méthode GetChanges d’une table de données.

    L’exemple suivant crée une table de données nommée changedRecordsTable et la remplit avec tous les enregistrements modifiés d’une autre table de données nommée dataTable1.

    DataTable changedRecordsTable = dataTable1.GetChanges();
    

Récupération de tous les enregistrements présentant un état de ligne spécifique

  • Appelez la méthode GetChanges d’un jeu de données ou d’une table de données et passez en argument une valeur d’énumération DataRowState.

    L’exemple suivant montre comment créer un jeu de données nommé addedRecords et le remplir avec les seuls enregistrements ajoutés au jeu de données dataSet1.

    DataSet addedRecords = dataSet1.GetChanges(DataRowState.Added);
    

    L’exemple suivant montre comment retourner tous les enregistrements ajoutés récemment à la table Customers :

    private NorthwindDataSet.CustomersDataTable GetNewRecords()
    {
        return (NorthwindDataSet.CustomersDataTable)
            northwindDataSet1.Customers.GetChanges(DataRowState.Added);
    }
    

Accès à la version d’origine d’une ligne de données

Lorsque des modifications sont apportées aux lignes de données, le jeu de données conserve à la fois la version d’origine (Original) et la nouvelle version (Current) de la ligne. Par exemple, votre application peut, avant d’appeler la méthode AcceptChanges, accéder aux différentes versions d’un enregistrement (définies dans l’énumération DataRowVersion) et traiter les modifications en conséquence.

Notes

Les différentes versions d’une ligne n’existent qu’après sa modification et avant que la méthode AcceptChanges n’ait été appelée. Une fois la méthode AcceptChanges appelée, la version actuelle et la version d’origine sont identiques.

Transmise avec l’index de colonne (ou le nom de la colonne sous forme de chaîne), la valeur DataRowVersion permet de retourner la valeur d’une version particulière d’une ligne de cette colonne. La colonne modifiée est identifiée pendant les événements ColumnChanging et ColumnChanged. C’est le moment d’inspecter les différentes versions de la ligne à des fins de validation. Si toutefois vous avez suspendu temporairement les contraintes, ces événements ne sont pas déclenchés. Vous devrez donc identifier programmatiquement les colonnes qui ont changé. Pour ce faire, vous pouvez boucler sur la collection Columns et comparer les différentes valeurs DataRowVersion.

Récupération de la version d’origine d’un enregistrement

  • Accédez à la valeur d’une colonne en transmettant la DataRowVersion de la ligne que vous souhaitez retourner.

    L’exemple suivant montre comment utiliser une valeur DataRowVersion pour obtenir la valeur d’origine d’un champ CompanyName dans une DataRow :

    string originalCompanyName;
    originalCompanyName = northwindDataSet1.Customers[0]
        ["CompanyName", DataRowVersion.Original].ToString();
    

Accès à la version actuelle d’une ligne de données

Récupération de la version actuelle d’un enregistrement

  • Accédez à la valeur d’une colonne, puis ajoutez un paramètre à l’index indiquant la version d’une ligne à retourner.

    L’exemple suivant montre comment utiliser une valeur DataRowVersion pour obtenir la valeur actuelle d’un champ CompanyName dans une DataRow :

    string currentCompanyName;
    currentCompanyName = northwindDataSet1.Customers[0]
        ["CompanyName", DataRowVersion.Current].ToString();