Comment : Implémenter une classe d’assistance DataSet JOIN dans Visual C# .NET

Pour obtenir une version Microsoft Visual Basic .NET de cet article, reportez-vous à la section.

325688 faire : implémenter une classe d’assistance DataSet JOIN dans Visual Basic .NET
Remarque: cet article fait partie d’une série d’articles DataSetHelper . Vous pouvez fusionner le code dans la classe DataSetHelper qui est répertorié dans cet article avec le code qui est fourni dans les autres articles DataSetHelper d’une classe unique avec un ensemble plus complet de la fonction.


Cet article fait référence aux espaces de noms bibliothèque de classes Microsoft.NET Framework suivant :
  • System.Data

DANS CETTE TÂCHE.

Résumé

Cet article étape par étape décrit comment implémenter et comment utiliser une classe DataSetHelper qui inclut des exemples de code pour créer un objet DataTable à partir de deux ou plusieurs définitions de table de données connexes et copier des enregistrements qui sont triés et filtrés à partir des objets DataTable source vers la table de donnéesde destination.

Pour ce faire, vous utilisez les méthodes publiques suivantes :

  • CreateJoinTable
  • InsertJoinInto
  • SelectJoinInto
La méthode SelectJoinInto appelle le CreateJoinTable et les méthodes InsertJoinInto . Vous pouvez également utiliser un membres de données et la méthode d’assistance privée pour stocker la liste des champs analysée.

La classe DataSetHelper inclut une variable de membre de groupe de données . Si vous le souhaitez, vous pouvez affecter un groupe de données de existant à la variable de membre de groupe de données . Si la variable membre pointe vers un valide de groupe de données, les objets DataTable qui le CreateJoinTable ou la méthode SelectJoinInto crée sont ajoutés au groupe de données. Dans les deux cas, l’appel de méthode retourne une référence à l’objet DataTable . La méthode InsertJoinInto nécessite une cible existante DataTable et ne retourne rien.

Pour plus d’informations sur les objets DataSet , cliquez sur le numéro ci-dessous pour afficher l’article correspondant dans la Base de connaissances Microsoft :

INFORMATIONS de 313485 : feuille de route pour ADO.NET DataSet, DataView et DataViewManager

Configuration requise

La liste suivante met en évidence les matériel, logiciel et infrastructure réseau recommandés ainsi que les service packs qui sont requis :

  • Microsoft Windows XP, Windows 2000 ou Windows NT 4.0 Service Pack 6
  • Microsoft Visual Studio .NET
Cet article suppose que vous maîtrisez les sujets suivants :

  • Syntaxe de Visual C# .NET
  • Syntaxe et les principes de base de ADO.NET

Classe d’environnement DataSetHelper

Le code dans cette section déclare la classe d’environnement à laquelle tous les articles DataSetHelper ajouter les méthodes et les variables de membre.
  1. Démarrez Visual Studio .NET.
  2. Dans le menu Fichier, pointez sur Nouveau, puis cliquez sur Projet.
  3. Dans la boîte de dialogue Nouveau projet , cliquez sur Projets Visual C# sous Types de projets, puis cliquez sur Bibliothèque de classes sous modèles.
  4. Dans la zone nom , tapez DataSetHelper.
  5. Remplacez le code de classe par le code suivant :
    public class DataSetHelper{
    public DataSet ds;

    public DataSetHelper(ref DataSet DataSet)
    {
    ds = DataSet;
    }
    public DataSetHelper()
    {
    ds = null;
    }
    }

    Vous pouvez utiliser les deux surcharges pour le constructeur pour créer une instance de la classe avec ou sans référence à un DataSetde valide. Pour une classe qui contient une référence à un DataSetde valide, les objets DataTable par les méthodes sont également ajoutés automatiquement au groupe de données.

Analyseur de champ de liste

Cette section contient le code pour un analyseur de champ de liste. La structure analysée est utilisée afin que le CreateJoinTable et les méthodes InsertJoinInto ne pas disposent d’analyse de la liste de champs. Ces méthodes doivent d’analyse la liste du champ si elles sont appelées à partir de la méthode SelectJoinInto ou à partir de votre propre code. La liste de champs analysée et la liste des champs non analysée sont stockés dans des variables de membre privé de la classe DataSetHelper .

  1. Ajoutez la définition suivante de classe privée dans la classe DataSetHelper que vous avez créé dans la section «Classe d’environnement DataSetHelper» :
    private class FieldInfo{
    public string RelationName;
    public string FieldName;//source table field name
    public string FieldAlias;//destination table field name
    public string Aggregate;
    }

    Remarque: cette classe est commune à d’autres articles DataSetHelper et contient des champs qui n’utilise pas de cet article.

  2. Ajoutez les variables de membre privé suivantes à la définition de classe immédiatement après la déclaration de groupe de données :
    private System.Collections.ArrayList m_FieldInfo; private string m_FieldList; 
  3. Ajoutez la méthode privée suivante à la définition de classe. Cette méthode est identique à la méthode qui est utilisée dans d’autres articles DataSetHelper .
    private void ParseFieldList(string FieldList, bool AllowRelation){
    /*
    * This code parses FieldList into FieldInfo objects and then
    * adds them to the m_FieldInfo private member
    *
    * FieldList systax: [relationname.]fieldname[ alias], ...
    */
    if (m_FieldList == FieldList) return;
    m_FieldInfo = new System.Collections.ArrayList();
    m_FieldList = FieldList;
    FieldInfo Field; string[] FieldParts;
    string[] Fields=FieldList.Split(',');
    int i;
    for (i=0; i<=Fields.Length-1; i++)
    {
    Field=new FieldInfo();
    //parse FieldAlias
    FieldParts = Fields[i].Trim().Split(' ');
    switch (FieldParts.Length)
    {
    case 1:
    //to be set at the end of the loop
    break;
    case 2:
    Field.FieldAlias=FieldParts[1];
    break;
    default:
    throw new Exception("Too many spaces in field definition: '" + Fields[i] + "'.");
    }
    //parse FieldName and RelationName
    FieldParts = FieldParts[0].Split('.');
    switch (FieldParts.Length)
    {
    case 1:
    Field.FieldName=FieldParts[0];
    break;
    case 2:
    if (AllowRelation==false)
    throw new Exception("Relation specifiers not permitted in field list: '" + Fields[i] + "'.");
    Field.RelationName = FieldParts[0].Trim();
    Field.FieldName=FieldParts[1].Trim();
    break;
    default:
    throw new Exception("Invalid field definition: " + Fields[i] + "'.");
    }
    if (Field.FieldAlias==null)
    Field.FieldAlias = Field.FieldName;
    m_FieldInfo.Add (Field);
    }
    }

Méthode de CreateJoinTable

Cette section contient le code de la méthode CreateJoinTable .

Voici la convention d’appel de la méthode CreateJoinTable :
dt = dsHelper.CreateJoinTable("TestTable", ds.Tables["Employees"],    "FirstName FName,LastName LName,DepartmentEmployee.DepartmentName Department");

Cet exemple appel crée un nouveau DataTable TableName de TestTable et trois champs (LName, FName et service). Ces trois champs ont les mêmes données de type en tant que prénom et les champs LastName de la table employés et le champ DepartmentName dans la table parente qui est accessible via l’objet DepartmentEmployee DataRelation .


Pour spécifier les champs dans la liste de champs, utilisez la syntaxe suivante :
[relationname.]fieldname[ alias], ...
Notez les informations suivantes pour que cette syntaxe :

  • ColumnName et les propriétés de type de données sont les seules propriétés qui sont copiées dans la table de donnéesde destination.
  • Pour les champs qui contiennent une expression, le résultat est copié.
  • Vous pouvez renommer un champ dans la table de données de destination en spécifiant un nom d’alias.
  • La liste de champs peut contenir un sous-ensemble de noms de champs qui sont répertoriés dans un ordre différent de celui de l’ordre de la source de table de données. Si la liste de champs est vide, une exception est levée.
  • DataRelation doit concerner les tables parent. Par exemple, si vous souhaitez créer une table qui combine des champs des tables Orders, les employés et les clients, vous devez utiliser la table Orders comme table source et ensuite référencer des champs dans les tables employés et des clients au moyen de relations.
Pour appeler la méthode CreateJoinTable , ajoutez la méthode suivante à la classe DataSetHelper que vous avez créé dans la section «Classe d’environnement DataSetHelper» :
public DataTable CreateJoinTable(string TableName, DataTable SourceTable, string FieldList){
/*
* Creates a table based on fields of another table and related parent tables
*
* FieldList syntax: [relationname.]fieldname[ alias][,[relationname.]fieldname[ alias]]...
*/
if (FieldList==null)
{
throw new ArgumentException("You must specify at least one field in the field list.");
//return CreateTable(TableName, SourceTable);
}
else
{
DataTable dt = new DataTable(TableName);
ParseFieldList(FieldList, true);
foreach(FieldInfo Field in m_FieldInfo)
{
if(Field.RelationName==null)
{
DataColumn dc = SourceTable.Columns[Field.FieldName];
dt.Columns.Add(dc.ColumnName, dc.DataType, dc.Expression);
}
else
{
DataColumn dc = SourceTable.ParentRelations[Field.RelationName].ParentTable.Columns[Field.FieldName];
dt.Columns.Add(dc.ColumnName, dc.DataType, dc.Expression);
}
}
if (ds!=null)
ds.Tables.Add(dt);
return dt;
}
}

Méthode de InsertJoinInto

Cette section contient le code de la méthode InsertJoinInto . La méthode InsertJoinInto copie les enregistrements qui sont triés et filtrés à partir de la table source et les tables associées à la table de destination. Lorsque vous appelez la propriété ParseFieldList , vous pouvez analyser des listes qui ont été précédemment analysés, si ces listes sont disponibles. Si la liste de champs est vide, une exception est levée.


Voici la convention d’appel de la méthode InsertJoinInto :
dsHelper.InsertJoinInto(ds.Tables["TestTable"], ds.Tables["Employees"],     "FirstName FName,LastName LName,DepartmentEmployee.DepartmentName Department", 
"EmployeeID<5", "BirthDate");

L’exemple d’appel copie d’enregistrements d' employés DataTable (et le champ DepartmentName de DataTableassocié) au TestTable DataTable, qui est filtré sur « EmployeeID < 5 » et est trié par date de naissance.

Remarque: le filtre et les expressions de tri s’appliquent uniquement à la table source et pas dans les tables associées.

Pour appeler la méthode InsertJoinInto , ajoutez la méthode suivante à la classe DataSetHelper que vous avez créé dans la section «Classe d’environnement DataSetHelper» :
public void InsertJoinInto(DataTable DestTable, DataTable SourceTable,     string FieldList, string RowFilter, string Sort)
{
/*
* Copies the selected rows and columns from SourceTable and inserts them into DestTable
* FieldList has same format as CreatejoinTable
*/
if (FieldList==null)
{
throw new ArgumentException("You must specify at least one field in the field list.");
//InsertInto(DestTable, SourceTable, RowFilter, Sort);
}
else
{
ParseFieldList(FieldList, true);
DataRow[] Rows = SourceTable.Select(RowFilter, Sort);
foreach(DataRow SourceRow in Rows)
{
DataRow DestRow = DestTable.NewRow();
foreach(FieldInfo Field in m_FieldInfo)
{
if(Field.RelationName==null)
{
DestRow[Field.FieldName] = SourceRow[Field.FieldName];
}
else
{
DataRow ParentRow = SourceRow.GetParentRow(Field.RelationName);
DestRow[Field.FieldName] = ParentRow[Field.FieldName];
}
}
DestTable.Rows.Add(DestRow);
}
}
}

Méthode de SelectJoinInto

Cette section contient le code de la méthode SelectJoinInto . Cette méthode est une combinaison de la CreateJoinTable et les méthodes InsertJoinInto . La méthode SelectJoinInto crée un nouveau DataTable basé sur DataTable objets et copie les enregistrements existants qui sont triés et filtrés dans la nouvelle table de données.


Voici la convention d’appel de la méthode SelectJoinInto :
dt = dsHelper.SelectInto("TestTable", ds.Tables["Employees"],     "FirstName FName,LastName LName,DepartmentEmployee.DepartmentName Department", "EmployeeID<5", "BirthDate");

Cet appel de l’exemple crée un DataTable nommé TestTable avec trois champs. Ces trois champs sont basés sur le prénom et les champs nom du DataTable employés et le champ DepartmentName du DataTable qui est référencé par le biais de la DepartmentEmployee DataRelation. Puis cet exemple copie les enregistrements d' employés DataTable au TestTable DataTable, qui est filtré sur « EmployeeID < 5 » et est trié par date de naissance.

Remarque: le filtre et les expressions de tri s’appliquent uniquement à la table source et pas dans les tables connexes.

Pour appeler la méthode SelectJoinInto , ajoutez la méthode suivante à la classe DataSetHelper que vous avez créé dans la section «Classe d’environnement DataSetHelper» :
public DataTable SelectJoinInto(string TableName, DataTable SourceTable, string FieldList, string RowFilter, string Sort){
/*
* Selects sorted, filtered values from one DataTable to another.
* Allows you to specify relationname.fieldname in the FieldList to include fields from
* a parent table. The Sort and Filter only apply to the base table and not to related tables.
*/
DataTable dt = CreateJoinTable(TableName, SourceTable, FieldList);
InsertJoinInto(dt, SourceTable, FieldList, RowFilter, Sort);
return dt;
}

Test de l’Application

  1. Enregistrer, puis compilez la classe DataSetHelper que vous avez créé dans les sections précédentes.
  2. Suivez ces étapes pour créer une nouvelle Application de Windows Visual C# :
    1. Démarrez Visual Studio .NET.
    2. Dans le menu Fichier, pointez sur Nouveau, puis cliquez sur Projet.
    3. Dans la boîte de dialogue Nouveau projet , cliquez sur Projets Visual C# sous Types de projets, puis cliquez sur Application Windows sous modèles.
  3. Dans l’Explorateur de solutions, avec le bouton droit de la solution, puis cliquez sur Ajouter un projet existant. Ajoutez le projet DataSetHelper.
  4. Dans le menu projet, cliquez sur Ajouter une référence.
  5. Dans la boîte de dialogue Ajouter une référence , cliquez sur l’onglet projets , puis ajoutez une référence au projet DataSetHelper dans l’application Windows Form.
  6. Dans le Concepteur de formulaires, faites glisser trois contrôles Button et un contrôle DataGrid à partir de la boîte à outils vers le formulaire. Nommez les boutons btnCreateJoin, btnInsertJoinIntoet btnSelectJoinInto. Conservez le nom par défaut pour le contrôle DataGrid (dataGrid1).
  7. Dans le code du formulaire, ajoutez l’instruction Using suivante en haut de la fenêtre de Code :
    using System.Data;
  8. Ajoutez les déclarations de variable suivantes à la définition du formulaire :
    DataSet ds; DataSetHelper.DataSetHelper dsHelper;
  9. Ajoutez le code suivant à l’événement Form_Load :
    ds = new DataSet();dsHelper = new DataSetHelper.DataSetHelper(ref ds);
    //Create source tables
    DataTable dt = new DataTable("Employees");
    dt.Columns.Add("EmployeeID",Type.GetType("System.Int32") );
    dt.Columns.Add("FirstName", Type.GetType("System.String"));
    dt.Columns.Add("LastName", Type.GetType("System.String"));
    dt.Columns.Add("BirthDate", Type.GetType("System.DateTime"));
    dt.Columns.Add("JobTitle", Type.GetType("System.String"));
    dt.Columns.Add("DepartmentID", Type.GetType("System.Int32"));
    dt.Rows.Add(new object[] {1, "Tommy", "Hill", new DateTime(1970, 12, 31), "Manager", 42});
    dt.Rows.Add(new object[] {2, "Brooke", "Sheals", new DateTime(1977, 12, 31), "Manager", 23});
    dt.Rows.Add(new object[] {3, "Bill", "Blast", new DateTime(1982, 5, 6), "Sales Clerk", 42});
    dt.Rows.Add(new object[] {1, "Kevin", "Kline", new DateTime(1978, 5, 13), "Sales Clerk", 42});
    dt.Rows.Add(new object[] {1, "Martha", "Seward", new DateTime(1976, 7, 4), "Sales Clerk", 23});
    dt.Rows.Add(new object[] {1, "Dora", "Smith", new DateTime(1985, 10, 22), "Trainee", 42});
    dt.Rows.Add(new object[] {1, "Elvis", "Pressman", new DateTime(1972, 11, 5), "Manager", 15});
    dt.Rows.Add(new object[] {1, "Johnny", "Cache", new DateTime(1984, 1, 23), "Sales Clerk", 15});
    dt.Rows.Add(new object[] {1, "Jean", "Hill", new DateTime(1979, 4, 14), "Sales Clerk", 42});
    dt.Rows.Add(new object[] {1, "Anna", "Smith", new DateTime(1985, 6, 26), "Trainee", 15});
    ds.Tables.Add(dt);

    dt = new DataTable("Departments");
    dt.Columns.Add("DepartmentID", Type.GetType("System.Int32"));
    dt.Columns.Add("DepartmentName", Type.GetType("System.String"));
    dt.Rows.Add(new object[] {15, "Men's Clothing"});
    dt.Rows.Add(new object[] {23, "Women's Clothing"});
    dt.Rows.Add(new object[] {42, "Children's Clothing"});
    ds.Tables.Add(dt);

    ds.Relations.Add("DepartmentEmployee", ds.Tables["Departments"].Columns["DepartmentID"],
    ds.Tables["Employees"].Columns["DepartmentID"]);

  10. Ajoutez le code suivant à l’événement btnCreateJoin_Click :
    dsHelper.CreateJoinTable("EmpDept",ds.Tables["Employees"],     "FirstName FName,LastName LName,BirthDate,DepartmentEmployee.DepartmentName Department");
    dataGrid1.SetDataBinding(ds, "EmpDept");

  11. Ajoutez le code suivant à l’événement btnInsertJoinInto_Click :
    dsHelper.InsertJoinInto(ds.Tables["EmpDept"], ds.Tables["Employees"],     "FirstName FName,LastName LName,BirthDate,DepartmentEmployee.DepartmentName Department",
    "JobTitle='Sales Clerk'", "DepartmentID");
    dataGrid1.SetDataBinding(ds, "EmpDept");

  12. Ajoutez le code suivant à l’événement btnSelectJoinInto_Click :
    dsHelper.SelectJoinInto("EmpDept2", ds.Tables["Employees"],    "FirstName,LastName,BirthDate BDate,DepartmentEmployee.DepartmentName Department", 
    "JobTitle='Manager'", "DepartmentID");
    dataGrid1.SetDataBinding(ds, "EmpDept2");

  13. Exécutez l’application, puis cliquez sur chacun des boutons. Notez que le contrôle DataGrid est rempli avec les tables et les données à partir du code.

    Remarque: vous pouvez uniquement cliquer sur les btnCreateJoin et les boutons de btnSelectJoinInto une seule fois. Si vous cliquez plusieurs fois sur un de ces boutons, vous recevez un message d’erreur que vous essayez d’ajouter la même table deux fois. En outre, vous devez cliquer sur btnCreateJoin avant de cliquer sur btnInsertJoinInto; dans le cas contraire, la destination DataTable n’est créé. Si vous cliquez sur le bouton btnInsertJoinInto plusieurs fois, vous remplissez le contrôle DataGrid avec des enregistrements en double.

Suggestions d’amélioration

  • ColumnName et les propriétés de type de données sont les seules propriétés qui sont copiées dans la table de donnéesde destination. Vous pouvez étendre la méthode Create table pour copier des propriétés supplémentaires, telles que la propriété MaxLength , ou vous pouvez créer de nouvelles colonnes de clé.
  • La propriété Expression n’est pas copiée ; à la place, le résultat est copié. Par conséquent, il est inutile d’ajouter des champs qui sont référencés par l’expression à la table de destination. En outre, la colonne de destination peut apparaître plus haut dans la liste des résultats d’une des colonnes que cette colonne dépend dans le cas contraire. Vous pouvez modifier la méthode CreateTable pour copier l' Expression (la colonne InsertInto ignore les colonnes avec une Expression), bien que ce soit les limites mentionnées plus haut dans ce paragraphe.
  • Vous pouvez fusionner les fonctionnalités de la CreateJoinTable, InsertJoinIntoet les méthodes SelectJoinInto dans les CreateTable, InsertIntoet les méthodes SelectInto . Pour plus d’informations sur la CreateTable, InsertIntoet les méthodes SelectInto , cliquez sur le numéro ci-dessous pour afficher l’article correspondant dans la Base de connaissances Microsoft :

    326009 faire : implémenter une classe d’assistance DataSet SELECT INTO dans Visual C# .NET
    Si vous ne souhaitez pas que ces méthodes de fusion, mais si vous avez les deux ensembles de méthodes dans une classe unique, vous pouvez activer le CreateJoinTable et les méthodes InsertJoinInto pour gérer une liste de champ vide en supprimant les instructions Throw et en commentaire les appels à la CreateTable et les méthodes InsertInto dans les lignes de code suivantes :
        if (FieldList==null)    {
    throw new ArgumentException("You must specify at least one field in the field list.");
    //return CreateTable(TableName, SourceTable);
    }

    - et -
        if (FieldList==null)    {
    throw new ArgumentException("You must specify at least one field in the field list.");
    //InsertInto(DestTable, SourceTable, RowFilter, Sort);
    }

Résolution des problèmes

  • Fieldname et les parties de l’alias de la liste de champs doivent être conforme aux conventions de dénomination de DataColumn . L’analyseur restreint également les noms, dans la mesure où le nom ne doit pas contenir un point (.), une virgule (,) ou un espace ().
  • Si vous cliquez plusieurs fois sur un bouton, la même table est ajoutée deux fois pour le groupe de données, ce qui résulte en une exception. Pour contourner ce problème, vous pouvez ajouter du code à l’application de test pour vérifier si une table de données du même nom existe déjà. Également, vous pouvez créer la classe DataSetHelper sans une référence à un groupe de données et puis de lier la propriété DataGrid.DataSource directement à la variable dt au lieu d’à l’aide de l’appel de la méthode SetDataBinding .
  • Si la table source utilise des types de données personnalisés (c'est-à-dire une classe), vous devez ajouter du code à la méthode InsertJoinInto pour effectuer une copie complète des données. Dans le cas contraire, seule une référence est copiée.
Propriétés

ID d'article : 326080 - Dernière mise à jour : 27 janv. 2017 - Révision : 1

Commentaires