mardi 25 janvier 2011

ADO.NET - Aide mémoire - 3/4 : DataView

Le présent article fait parti d'une suite logique de 4 articles: "ADO.NET - Aide mémoire - 1/4 : Execution, Parametres, StoredProc, DataReader",  "ADO.NET - Aide mémoire - 2/4 : DataSet", "ADO.NET - Aide mémoire - 2/4 : DataView" et "ADO.NET - Aide mémoire - 4/4 : Tutoriel"

DataView
Un DataView permet de créer différentes vues des données stockées dans une DataTable, une aptitude qui est souvent utilisée dans les opérations de data-binding. En utilisant un DataView, il est possible d'exposer les données d'une table avec un ordre de tri différent, il est également possible de filtrer les données par état (avant/après modification) ou encore filtrer sur base d'une expression (équivalent d'une clause "where" en sql).

Un DataView fournit une vue dynamique des données stockées dans la DataTable sous-jacente: le contenu, l'ordre de tri, et aspects relationnels reflètent les modifications tels qu'elles se présentent. Cette caractéristique diffère de méthode "Select" de la DataTable qui produit un tableau de DataRow depuis la DataTable sur base d'un filtre et/ou tri particulier: ce contenu reproduit les modifications dans la table sous-jacente, mais les aspects relationnels et l'ordonnancement restent statiques. Les capacités dynamiques du DataView en font un candidat idéal pour l'utilisation de data-binding.

Un DataView procure une vue dynamique d'un ensemble de données unique, un peu comme les vues d'une base de données, auquel il est possible d'appliquer différents ordres de tri et critères de sélection. Au contraire d'un vue en DB, un DataView ne peut pas être manipulé comme une table et ne peut pas fournir une jointure entre plusieurs tables. Vous ne pouvez pas non plus exclure des colonnes qui existent dans la table source, ni ajouter des colonnes tels que des colonnes calculées qui ne se trouveraient pas dans la table source.

Vous pouvez utiliser une DataViewManager pour gérer la configuration des vues pour toutes les tables d'un DataSet. Le DataViewManager procure la possibilité de gérer la configuration du DefaultView de chaque table de façon pratique. Lorsqu'un contrôle est lié (bind) à plus d'une table d'un DataSet, faire le binding vers un DataViewManager est alors un choix idéal.

Voici quelques références complémentaires:
  • Page reprenant les Articles de Microsoft concernant les DataViews, articles énumérés et décrits ci-dessous.
  • Creating a DataView (ADO.NET)
    Décrit comment créer un DataView pour un DataTable
  • Sorting and Filtering Data (ADO.NET)
    Montre comment initialiser les propriétés d'un DataView pour retourner un sous-ensemble des enregistrements de données qui satisfont les critères de filtrage, ou qui retourne les données dans un ordre particulier.
  • DataRows and DataRowViews (ADO.NET)
    Explique comment accéder aux données exposées par le DataView.
  • Finding Rows (ADO.NET)
    Explique comment retrouver un enregistrement particulier dans un DataView
  • ChildViews and Relations (ADO.NET)
    Décrit comment créer une vue à partir d'une relation master-detail (parent-child) en utilisant un DataView.
  • Modifying DataViews (ADO.NET)
    Explique comment modifier les données de la DataTable sous-jacente à partir d'un DataView, incluant également l'activation/désactivation des mise-à-jours (updates).
  • Handling DataView Events (ADO.NET)
    Explique comment utiliser l'évènement ListChanged pour recevoir une notification lorsque le contenu ou l'ordre de tri d'un DataView est en cours de modification.
  • Managing DataViews (ADO.NET)
    Explique comment utiliser un DataViewManager pour gérer les configurations des DataView pour chaque table du DataSet.
Exemple de relation Master-Detail et ChildView
Directement issu d'un des articles MSDN, voici un petit morceau de code qui montre comment définir une relation Master-Detail dans un DataSet mais aussi comment l'exploiter pour créer un ChildView (CreateChildView)
DataTable catTable = catDS.Tables["Categories"];
DataTable prodTable = catDS.Tables["Products"];

// Create a relation between the Categories and Products tables.
DataRelation relation = catDS.Relations.Add("CatProdRel", 
    catTable.Columns["CategoryID"],
    prodTable.Columns["CategoryID"]);

// Create DataViews for the Categories and Products tables.
DataView catView = new DataView(catTable, "", "CategoryName", 
  DataViewRowState.CurrentRows);
DataView prodView;

// Iterate through the Categories table.
foreach (DataRowView catDRV in catView)
{
  Console.WriteLine(catDRV["CategoryName"]);

  // Create a DataView of the child product records.
  prodView = catDRV.CreateChildView(relation);
  prodView.Sort = "ProductName";

  foreach (DataRowView prodDRV in prodView)
    Console.WriteLine("\t" + prodDRV["ProductName"]);
}

Autre Exemple issus de MSDN - DataViewManager, chargement Dataset.

Cet autre exemple de MSDN (légèrement adapté) est censé démontrer l'usage du DataViewManager.
Personnellement, je crois qu'il y a moyen de mieux faire.
Par contre, ce qui est beaucoup intéressant, c'est le chargement de plusieurs tables et de leurs relations dans un seul dataset. Tables de la DB AdventureWorks.

Fichier source: AdoNet_DataViewManager.cs.

using System;using System.Collections.Generic;using System.Data;using System.Data.SqlClient;using System.Windows.Forms;
public class MyClass
{
    public static void RunSnippet()
    {
        // Adventure Works creation script and database CAN BE DOWNLOADED from CodePlex
        //    http://sqlserversamples.codeplex.com/
        //
        SqlConnection connection = new SqlConnection( "Data Source=localhost;Initial Catalog=AdventureWorksLT2008;Integrated Security=SSPI;" );
        // Assumes connection is a valid SqlConnection to Northwind.
        // Create a Connection, DataAdapters, and a DataSet.
        SqlDataAdapter custDA = new SqlDataAdapter(
        "SELECT CustomerID, CompanyName FROM SalesLT.Customer", connection);
        SqlDataAdapter orderDA = new SqlDataAdapter(
        "SELECT SalesOrderID, CustomerID FROM SalesLT.SalesOrderHeader", connection);
        SqlDataAdapter ordDetDA = new SqlDataAdapter(
        "SELECT SalesOrderID, ProductID, OrderQty FROM SalesLT.SalesOrderDetail", connection);
        
        DataSet custDS = new DataSet();
        
        // Open the Connection.
        connection.Open();

        // Fill the DataSet with schema information and data.
        custDA.MissingSchemaAction = MissingSchemaAction.AddWithKey;
        orderDA.MissingSchemaAction = MissingSchemaAction.AddWithKey;
        ordDetDA.MissingSchemaAction = MissingSchemaAction.AddWithKey;
    
        custDA.Fill(custDS, "Customers");
        orderDA.Fill(custDS, "Orders");
        ordDetDA.Fill(custDS, "OrderDetails");
    
        // Close the Connection.
        connection.Close();
    
        // Create relationships.
        custDS.Relations.Add("CustomerOrders",
            custDS.Tables["Customers"].Columns["CustomerID"],
            custDS.Tables["Orders"].Columns["CustomerID"]);
    
        custDS.Relations.Add("OrderDetails",
            custDS.Tables["Orders"].Columns["SalesOrderID"],
            custDS.Tables["OrderDetails"].Columns["SalesOrderID"]);
    
        // Create default DataView settings.
        DataViewManager viewManager = new DataViewManager(custDS);
        
        foreach (DataViewSetting viewSetting in viewManager.DataViewSettings)
        viewSetting.ApplyDefaultSort = true;
        
        viewManager.DataViewSettings["Customers"].Sort = "CompanyName";
        
        // Bind to a DataGrid.
        //   Note: N'affichera absolument rien sous snippet compiler
        System.Windows.Forms.DataGrid grid = new System.Windows.Forms.DataGrid();
        grid.SetDataBinding(viewManager, "Customers");

    }
    
    #region Helper methods
    ...
    #endregion
}

Aucun commentaire: