Partager via


Création d’une couche d’accès aux données (C#)

par Scott Mitchell

Télécharger le PDF

Dans ce tutoriel, nous allons commencer à partir du début et créer la couche d’accès aux données (DAL), à l’aide de DataSets typés, pour accéder aux informations d’une base de données.

Introduction

En tant que développeurs web, nos vies tournent autour de l’utilisation des données. Nous créons des bases de données pour stocker les données, le code pour les récupérer et les modifier, ainsi que les pages web pour les collecter et les résumer. Il s’agit du premier didacticiel d’une longue série qui explorera les techniques d’implémentation de ces modèles courants dans ASP.NET 2.0. Nous allons commencer par créer une architecture logicielle composée d’une couche d’accès aux données (DAL) à l’aide de DataSets typés, d’une couche logique métier (BLL) qui applique des règles métier personnalisées et d’une couche de présentation composée de pages ASP.NET qui partagent une mise en page commune. Une fois que ce travail de base back-end a été posé, nous allons passer à la création de rapports, en montrant comment afficher, résumer, collecter et valider des données à partir d’une application web. Ces didacticiels sont destinés à être concis et fournissent des instructions pas à pas avec de nombreuses captures d’écran pour vous guider visuellement dans le processus. Chaque didacticiel est disponible dans les versions C# et Visual Basic et inclut un téléchargement du code complet utilisé. (Ce premier tutoriel est assez long, mais le reste est présenté dans des blocs beaucoup plus digestibles.)

Pour ces didacticiels, nous allons utiliser une version Microsoft SQL Server 2005 Express Edition de la base de données Northwind placée dans le répertoire App_Data . Outre le fichier de base de données, le dossier App_Data contient également les scripts SQL pour la création de la base de données, au cas où vous souhaitez utiliser une autre version de base de données. Si vous utilisez une autre version de SQL Server de la base de données Northwind, vous devez mettre à jour le paramètre NORTHWNDConnectionString dans le fichier Web.config de l’application. L’application web a été créée à l’aide de Visual Studio 2005 Professional Edition en tant que projet de site web basé sur le système de fichiers. Toutefois, tous les didacticiels fonctionneront également bien avec la version gratuite de Visual Studio 2005, Visual Web Developer.

Dans ce tutoriel, nous allons commencer à partir du début et créer la couche d’accès aux données (DAL), suivie de la création de la couche logique métier (BLL) dans le deuxième tutoriel, et de travailler sur la mise en page et la navigation dans le troisième. Les didacticiels après le troisième devront s’appuyer sur la base des trois premiers. Nous avons beaucoup à couvrir dans ce premier tutoriel, alors démarrez Visual Studio et commençons !

Étape 1 : Création d’un projet web et connexion à la base de données

Avant de pouvoir créer notre couche d’accès aux données (DAL), nous devons d’abord créer un site web et configurer notre base de données. Commencez par créer un site web basé sur le système de fichiers ASP.NET. Pour ce faire, accédez au menu Fichier et choisissez Nouveau site web, en affichant la boîte de dialogue Nouveau site web. Choisissez le modèle de site web ASP.NET, définissez la liste déroulante Emplacement sur Système de fichiers, choisissez un dossier pour placer le site web et définissez la langue sur C#.

Créer un site web basé sur le système de fichiers

Figure 1 : Créer un site web basé sur le système de fichiers (cliquez pour afficher l’image de taille complète)

Cela crée un site web avec une page Default.aspx ASP.NET et un dossier App_Data .

Une fois le site web créé, l’étape suivante consiste à ajouter une référence à la base de données dans l’Explorateur de serveurs de Visual Studio. En ajoutant une base de données à l’Explorateur de serveurs, vous pouvez ajouter des tables, des procédures stockées, des vues, et ainsi de suite à partir de Visual Studio. Vous pouvez également afficher les données de table ou créer vos propres requêtes manuellement ou graphiquement via le Générateur de requêtes. En outre, lorsque nous créons les jeux de données typés pour le dal, nous devons pointer Visual Studio vers la base de données à partir de laquelle les jeux de données typés doivent être construits. Bien que nous puissions fournir ces informations de connexion à ce stade dans le temps, Visual Studio remplit automatiquement une liste déroulante des bases de données déjà inscrites dans l’Explorateur de serveurs.

Les étapes d’ajout de la base de données Northwind à l’Explorateur de serveurs dépendent de l’utilisation de la base de données SQL Server 2005 Express Edition dans le dossier App_Data ou si vous avez une configuration de serveur de base de données Microsoft SQL Server 2000 ou 2005 que vous souhaitez utiliser à la place.

Utilisation d’une base de données dans le dossier App_Data

Si vous n’avez pas de serveur de base de données SQL Server 2000 ou 2005 à vous connecter, ou si vous souhaitez simplement éviter d’avoir à ajouter la base de données à un serveur de base de données, vous pouvez utiliser la version SQL Server 2005 Express Edition de la base de données Northwind située dans le dossier App_Data du site web téléchargé (NORTHWND). MDF).

Une base de données placée dans le dossier App_Data est automatiquement ajoutée à l’Explorateur de serveurs. En supposant que SQL Server 2005 Express Edition soit installé sur votre ordinateur, vous devez voir un nœud nommé NORTHWND. MDF dans l’Explorateur de serveurs, que vous pouvez développer et explorer ses tables, vues, procédure stockée, etc. (voir la figure 2).

Le dossier App_Data peut également contenir les fichiers .mdb Microsoft Access, qui, comme leurs équivalents SQL Server, sont automatiquement ajoutés à l’Explorateur de serveurs. Si vous ne souhaitez pas utiliser d’options SQL Server, vous pouvez toujours installer la base de données et les applications Northwind Traders et les déplacer dans le répertoire App_Data . Gardez à l’esprit toutefois que les bases de données Access ne sont pas aussi riches en fonctionnalités que SQL Server et ne sont pas conçues pour être utilisées dans les scénarios de site web. En outre, quelques didacticiels de 35+ utilisent certaines fonctionnalités au niveau de la base de données qui ne sont pas prises en charge par Access.

Connexion à la base de données dans un serveur de base de données Microsoft SQL Server 2000 ou 2005

Vous pouvez également vous connecter à une base de données Northwind installée sur un serveur de base de données. Si le serveur de base de données n’a pas encore installé la base de données Northwind, vous devez d’abord l’ajouter au serveur de base de données en exécutant le script d’installation inclus dans le téléchargement de ce didacticiel.

Une fois la base de données installée, accédez à l’Explorateur de serveurs dans Visual Studio, cliquez avec le bouton droit sur le nœud Connexions de données, puis choisissez Ajouter une connexion. Si vous ne voyez pas l’Explorateur de serveurs accéder à l’Affichage/Explorateur de serveurs, ou appuyez sur Ctrl+Alt+S. La boîte de dialogue Ajouter une connexion s’affiche, où vous pouvez spécifier le serveur auquel se connecter, les informations d’authentification et le nom de la base de données. Une fois que vous avez correctement configuré les informations de connexion de base de données et cliqué sur le bouton OK, la base de données est ajoutée en tant que nœud sous le nœud Connexions de données. Vous pouvez développer le nœud de base de données pour explorer ses tables, vues, procédures stockées, et ainsi de suite.

Ajouter une connexion à la base de données Northwind de votre serveur de base de données

Figure 2 : Ajouter une connexion à la base de données Northwind de votre serveur de base de données Northwind

Étape 2 : Création de la couche d’accès aux données

Lorsque vous utilisez des données, une option consiste à incorporer la logique spécifique aux données directement dans la couche de présentation (dans une application web, les pages ASP.NET composent la couche de présentation). Cela peut prendre la forme d’écrire ADO.NET code dans la partie de code de la page ASP.NET ou à l’aide du contrôle SqlDataSource à partir de la partie de balisage. Dans les deux cas, cette approche couple étroitement la logique d’accès aux données avec la couche de présentation. Toutefois, l’approche recommandée consiste à séparer la logique d’accès aux données de la couche présentation. Cette couche distincte est appelée couche d’accès aux données, DAL pour un court terme, et est généralement implémentée en tant que projet de bibliothèque de classes distinct. Les avantages de cette architecture en couches sont bien documentés (consultez la section « Autres lectures » à la fin de ce tutoriel pour plus d’informations sur ces avantages) et est l’approche que nous adopterons dans cette série.

Tout le code spécifique à la source de données sous-jacente, comme la création d’une connexion à la base de données, l’émission de commandes SELECT, INSERT, UPDATE et DELETE, et ainsi de suite doit se trouver dans le DAL. La couche de présentation ne doit pas contenir de références à ce code d’accès aux données, mais doit plutôt effectuer des appels au dal pour toutes les demandes de données. Les couches d’accès aux données contiennent généralement des méthodes d’accès aux données de base de données sous-jacentes. La base de données Northwind, par exemple, contient des tables Products et Categories qui enregistrent les produits à vendre et les catégories auxquelles elles appartiennent. Dans notre DAL, nous aurons des méthodes comme :

  • GetCategories(), qui retourne des informations sur toutes les catégories
  • GetProducts(), qui retourne des informations sur tous les produits
  • GetProductsByCategoryID(categoryID), qui retourne tous les produits appartenant à une catégorie spécifiée
  • GetProductByProductID(productID), qui retourne des informations sur un produit particulier

Ces méthodes, lorsqu’elles sont appelées, se connectent à la base de données, émettent la requête appropriée et retournent les résultats. Comment nous renvoyons ces résultats est important. Ces méthodes peuvent simplement retourner un DataSet ou DataReader rempli par la requête de base de données, mais dans l’idéal, ces résultats doivent être retournés à l’aide d’objets fortement typés. Un objet fortement typé est un objet dont le schéma est défini de manière rigide au moment de la compilation, tandis que l’inverse, un objet faiblement typé, est celui dont le schéma n’est pas connu tant que l’exécution n’est pas terminée.

Par exemple, DataReader et DataSet (par défaut) sont des objets faiblement typés, car leur schéma est défini par les colonnes retournées par la requête de base de données utilisée pour les remplir. Pour accéder à une colonne particulière à partir d’un DataTable faiblement typé, nous devons utiliser la syntaxe comme : DataTable. Rows[index]["columnName"]. La saisie libre de DataTable dans cet exemple est exposée par le fait que nous devons accéder au nom de colonne à l’aide d’une chaîne ou d’un index ordinal. Un DataTable fortement typé, d’autre part, aura chacune de ses colonnes implémentées en tant que propriétés, ce qui entraîne le code qui ressemble à : DataTable. Lignes[index].columnName.

Pour retourner des objets fortement typés, les développeurs peuvent créer leurs propres objets métier personnalisés ou utiliser des DataSets typés. Un objet métier est implémenté par le développeur en tant que classe dont les propriétés reflètent généralement les colonnes de la table de base de données sous-jacente que représente l’objet métier. Un DataSet typé est une classe générée pour vous par Visual Studio en fonction d’un schéma de base de données et dont les membres sont fortement typés en fonction de ce schéma. Le DataSet typé se compose de classes qui étendent les classes dataSet, DataTable et DataRow ADO.NET. Outre les DataTables fortement typés, les DataSets typés incluent désormais TableAdapters, qui sont des classes avec des méthodes permettant de remplir les DataTables de DataSet et de propager les modifications dans les DataTables dans la base de données.

Remarque

Pour plus d’informations sur les avantages et les inconvénients de l’utilisation de DataSets typés par rapport aux objets métier personnalisés, reportez-vous à la conception de composants de couche Données et à la transmission de données via des niveaux.

Nous allons utiliser des DataSets fortement typés pour l’architecture de ces didacticiels. La figure 3 illustre le flux de travail entre les différentes couches d’une application qui utilise des jeux de données typés.

Tout le code d’accès aux données est relégué au dal

Figure 3 : Tout le code d’accès aux données est relégué au dal (cliquez pour afficher l’image de taille complète)

Création d’un jeu de données typé et d’un adaptateur de table

Pour commencer à créer notre DAL, nous commençons par ajouter un DataSet Typd à notre projet. Pour ce faire, cliquez avec le bouton droit sur le nœud du projet dans le Explorateur de solutions et choisissez Ajouter un nouvel élément. Sélectionnez l’option DataSet dans la liste des modèles et nommez-la Northwind.xsd.

Choisir d’ajouter un nouveau jeu de données à votre projet

Figure 4 : Choisir d’ajouter un nouveau jeu de données à votre projet (cliquez pour afficher l’image de taille complète)

Après avoir cliqué sur Ajouter, lorsque vous êtes invité à ajouter le DataSet au dossier App_Code , choisissez Oui. Le Concepteur du Jeu de données typé s’affiche, et l’Assistant Configuration de TableAdapter démarre, ce qui vous permet d’ajouter votre premier TableAdapter au Jeu de données Typé.

Un DataSet typé sert de collection fortement typée de données ; il se compose d’instances DataTable fortement typées, chacune d’elles étant à son tour composée d’instances DataRow fortement typées. Nous allons créer un DataTable fortement typé pour chacune des tables de base de données sous-jacentes avec lesquelles nous devons travailler dans cette série de didacticiels. Commençons par créer un DataTable pour la table Products .

N’oubliez pas que les DataTables fortement typés n’incluent aucune information sur l’accès aux données à partir de leur table de base de données sous-jacente. Pour récupérer les données pour remplir dataTable, nous utilisons une classe TableAdapter, qui fonctionne comme couche d’accès aux données. Pour nos produits DataTable, TableAdapter contiendra les méthodes GetProducts(), GetProductByCategoryID(categoryID), et ainsi de suite, nous allons appeler à partir de la couche de présentation. Le rôle de DataTable est de servir d’objets fortement typés utilisés pour transmettre des données entre les couches.

L’Assistant Configuration de TableAdapter commence par vous inviter à sélectionner la base de données à utiliser. La liste déroulante affiche ces bases de données dans l’Explorateur de serveurs. Si vous n’avez pas ajouté la base de données Northwind à l’Explorateur de serveurs, vous pouvez cliquer sur le bouton Nouvelle connexion pour ce faire.

Choisissez la base de données Northwind dans la liste déroulante

Figure 5 : Choisir la base de données Northwind dans la liste déroulante (cliquez pour afficher l’image de taille complète)

Après avoir sélectionné la base de données et cliqué sur Suivant, vous êtes invité à enregistrer le chaîne de connexion dans le fichier Web.config. En enregistrant le chaîne de connexion vous éviterez de le coder en dur dans les classes TableAdapter, ce qui simplifie les choses si les informations chaîne de connexion changent à l’avenir. Si vous choisissez d’enregistrer le chaîne de connexion dans le fichier de configuration, il est placé dans la <section connectionStrings>, qui peut éventuellement être chiffré pour une sécurité améliorée ou modifiée ultérieurement via la nouvelle page de propriétés ASP.NET 2.0 dans l’outil d’administration de l’interface utilisateur utilisateur IIS, qui est plus idéal pour les administrateurs.

Enregistrer la chaîne de connexion sur Web.config

Figure 6 : Enregistrer la chaîne de connexion dans Web.config (cliquez pour afficher l’image de taille complète)

Ensuite, nous devons définir le schéma pour le premier DataTable fortement typé et fournir la première méthode pour notre TableAdapter à utiliser lors du remplissage du DataSet fortement typé. Ces deux étapes sont effectuées simultanément en créant une requête qui retourne les colonnes de la table que nous voulons refléter dans notre DataTable. À la fin de l’Assistant, nous allons donner un nom de méthode à cette requête. Une fois cette opération effectuée, cette méthode peut être appelée à partir de notre couche de présentation. La méthode exécute la requête définie et remplit un DataTable fortement typé.

Pour commencer à définir la requête SQL, nous devons d’abord indiquer comment le TableAdapter doit émettre la requête. Nous pouvons utiliser une instruction SQL ad hoc, créer une procédure stockée ou utiliser une procédure stockée existante. Pour ces didacticiels, nous allons utiliser des instructions SQL ad hoc.

Interroger les données à l’aide d’une instruction SQL ad hoc

Figure 7 : Interroger les données à l’aide d’une instruction SQL ad hoc (Cliquez pour afficher l’image de taille complète)

À ce stade, nous pouvons taper manuellement la requête SQL. Lors de la création de la première méthode dans TableAdapter, vous souhaitez généralement que la requête retourne les colonnes qui doivent être exprimées dans le DataTable correspondant. Pour ce faire, nous pouvons créer une requête qui retourne toutes les colonnes et toutes les lignes de la table Products :

Entrer la requête SQL dans la zone de texte

Figure 8 : Entrer la requête SQL dans la zone de texte (Cliquez pour afficher l’image de taille complète)

Vous pouvez également utiliser le Générateur de requêtes et construire graphiquement la requête, comme illustré dans la figure 9.

Créez la requête graphiquement, via l’Éditeur de requête

Figure 9 : Créer la requête graphiquement, via le Éditeur de requête (cliquez pour afficher l’image de taille complète)

Après avoir créé la requête, mais avant de passer à l’écran suivant, cliquez sur le bouton Options avancées. Dans les projets de site web, « Générer des instructions Insert, Update et Delete » est la seule option avancée sélectionnée par défaut ; si vous exécutez cet Assistant à partir d’une bibliothèque de classes ou d’un projet Windows, l’option « Utiliser la concurrence optimiste » est également sélectionnée. Laissez l’option « Utiliser la concurrence optimiste » désactivée pour l’instant. Nous examinerons l’accès concurrentiel optimiste dans les prochains didacticiels.

Sélectionnez uniquement l’option Générer l’insertion, la mise à jour et la suppression des instructions

Figure 10 : Sélectionner uniquement l’option Générer l’insertion, la mise à jour et la suppression des instructions (Cliquez pour afficher l’image de taille complète)

Après avoir vérifié les options avancées, cliquez sur Suivant pour passer à l’écran final. Ici, nous sommes invités à sélectionner les méthodes à ajouter à TableAdapter. Il existe deux modèles pour remplir des données :

  • Remplissez un DataTable avec cette approche, une méthode est créée qui prend un DataTable en tant que paramètre et la remplit en fonction des résultats de la requête. La classe ADO.NET DataAdapter, par exemple, implémente ce modèle avec sa méthode Fill().
  • Retournez un DataTable avec cette approche, la méthode crée et remplit dataTable pour vous et la retourne à mesure que les méthodes retournent la valeur.

Vous pouvez utiliser TableAdapter pour implémenter un ou les deux modèles suivants. Vous pouvez également renommer les méthodes fournies ici. Laissez les deux cases à cocher activées, même si nous utiliserons uniquement le dernier modèle dans ces didacticiels. En outre, renommons la méthode GetData plutôt générique en GetProducts.

Si cette case est cochée, la case finale « GenerateDBDirectMethods » crée des méthodes Insert(), Update() et Delete() pour TableAdapter. Si vous laissez cette option désactivée, toutes les mises à jour doivent être effectuées via la méthode Update() unique de TableAdapter, qui prend dans l’ensemble de données typé, un DataTable, un DataRow unique ou un tableau de DataRows. (Si vous avez décoché l’option « Générer des instructions d’insertion, de mise à jour et de suppression » des propriétés avancées de la figure 9, cette case à cocher n’aura aucun effet.) Laissez cette case à cocher activée.

Modifier le nom de la méthode de GetData en GetProducts

Figure 11 : Modifier le nom de la méthode de GetData en GetProducts (cliquez pour afficher l’image de taille complète)

Terminez l’Assistant en cliquant sur Terminer. Une fois l’Assistant fermé, nous sommes retournés au Concepteur DataSet qui affiche le DataTable que nous venons de créer. Vous pouvez voir la liste des colonnes dans Products DataTable (ProductID, ProductName, etc.), ainsi que les méthodes de ProductsTableAdapter (Fill() et GetProducts()).

DataTable et ProductsTableAdapter ont été ajoutés à l’ensemble de données typé

Figure 12 : DataTable de produits et ProductsTableAdapter ont été ajoutés à l’ensemble de données typé (cliquez pour afficher l’image de taille complète)

À ce stade, nous avons un Jeu de données typé avec une seule DataTable (Northwind.Products) et une classe DataAdapter fortement typée (NorthwindTableAdapters.ProductsTableAdapter) avec une méthode GetProducts(). Ces objets peuvent être utilisés pour accéder à une liste de tous les produits à partir de code comme :

NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
    new NorthwindTableAdapters.ProductsTableAdapter();
Northwind.ProductsDataTable products;
products = productsAdapter.GetProducts();
foreach (Northwind.ProductsRow productRow in products)
    Response.Write("Product: " + productRow.ProductName + "<br />");

Ce code n’a pas exigé que nous écrivions un bit de code spécifique à l’accès aux données. Nous n’avons pas dû instancier des classes ADO.NET, nous n’avons pas dû faire référence à des chaîne de connexion, requêtes SQL ou procédures stockées. Au lieu de cela, TableAdapter fournit le code d’accès aux données de bas niveau pour nous.

Chaque objet utilisé dans cet exemple est également fortement typé, ce qui permet à Visual Studio de fournir intelliSense et la vérification du type au moment de la compilation. Et le meilleur de tous les DataTables retournés par TableAdapter peut être lié à ASP.NET contrôles Web de données, tels que GridView, DetailsView, DropDownList, CheckBoxList, etc. L’exemple suivant illustre la liaison de DataTable retournée par la méthode GetProducts() à un GridView dans seulement trois lignes de code dans le gestionnaire d’événements Page_Load .

AllProducts.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AllProducts.aspx.cs"
    Inherits="AllProducts" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>View All Products in a GridView</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h2>
            All Products</h2>
        <p>
            <asp:GridView ID="GridView1" runat="server"
             CssClass="DataWebControlStyle">
               <HeaderStyle CssClass="HeaderStyle" />
               <AlternatingRowStyle CssClass="AlternatingRowStyle" />
            </asp:GridView>
             </p>
    </div>
    </form>
</body>
</html>

AllProducts.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindTableAdapters;
public partial class AllProducts : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ProductsTableAdapter productsAdapter = new
         ProductsTableAdapter();
        GridView1.DataSource = productsAdapter.GetProducts();
        GridView1.DataBind();
    }
}

La liste des produits s’affiche dans un GridView

Figure 13 : La liste des produits s’affiche dans un GridView (cliquez pour afficher une image de taille complète)

Bien que cet exemple exige que nous écrivions trois lignes de code dans le gestionnaire d’événements Page_Load de la page ASP.NET , dans les didacticiels futurs, nous allons examiner comment utiliser ObjectDataSource pour récupérer de manière déclarative les données à partir du dal. Avec ObjectDataSource, nous n’aurons pas besoin d’écrire de code et obtiendrons également la prise en charge de la pagination et du tri !

Étape 3 : Ajout de méthodes paramétrables à la couche d’accès aux données

À ce stade, notre classe ProductsTableAdapter a une méthode, GetProducts(), qui retourne tous les produits de la base de données. Tout en étant en mesure de travailler avec tous les produits est certainement utile, il existe des moments où nous voulons récupérer des informations sur un produit spécifique, ou tous les produits appartenant à une catégorie particulière. Pour ajouter de telles fonctionnalités à notre couche d’accès aux données, nous pouvons ajouter des méthodes paramétrables à TableAdapter.

Ajoutons la méthode GetProductsByCategoryID(categoryID). Pour ajouter une nouvelle méthode au dal, revenez au Concepteur DataSet, cliquez avec le bouton droit dans la section ProductsTableAdapter , puis choisissez Ajouter une requête.

Cliquez avec le bouton droit sur TableAdapter et choisissez Ajouter une requête

Figure 14 : Cliquez avec le bouton droit sur TableAdapter et choisissez Ajouter une requête

Nous sommes d’abord invités à savoir si nous voulons accéder à la base de données à l’aide d’une instruction SQL ad hoc ou d’une procédure stockée nouvelle ou existante. Nous allons choisir d’utiliser à nouveau une instruction SQL ad hoc. Ensuite, nous sommes invités à savoir quel type de requête SQL nous aimerions utiliser. Étant donné que nous voulons retourner tous les produits appartenant à une catégorie spécifiée, nous voulons écrire une instruction SELECT qui retourne des lignes.

Choisir de créer une instruction SELECT qui renvoie des lignes

Figure 15 : Choisir de créer une instruction SELECT qui renvoie des lignes (cliquez pour afficher l’image de taille complète)

L’étape suivante consiste à définir la requête SQL utilisée pour accéder aux données. Étant donné que nous voulons retourner uniquement les produits appartenant à une catégorie particulière, j’utilise la même instruction SELECT de GetProducts(), mais ajoutez la clause WHERE suivante : WHERE CategoryID = @CategoryID. Le paramètre @CategoryID indique à l’Assistant TableAdapter que la méthode que nous créons nécessite un paramètre d’entrée du type correspondant (à savoir, un entier nullable).

Entrer une requête pour renvoyer uniquement des produits dans une catégorie spécifiée

Figure 16 : Entrer une requête pour renvoyer uniquement des produits dans une catégorie spécifiée (cliquez pour afficher l’image de taille complète)

Au cours de la dernière étape, nous pouvons choisir les modèles d’accès aux données à utiliser, ainsi que personnaliser les noms des méthodes générées. Pour le modèle De remplissage, nous allons remplacer le nom par FillByCategoryID et pour le modèle de retour DataTable (méthodes GetX ), utilisons GetProductsByCategoryID.

Choisir les noms des méthodes TableAdapter

Figure 17 : Choisir les noms des méthodes TableAdapter (Cliquez pour afficher l’image de taille complète)

Une fois l’Assistant terminé, le Concepteur DataSet inclut les nouvelles méthodes TableAdapter.

Les produits peuvent maintenant être interrogés par catégorie

Figure 18 : Les produits peuvent maintenant être interrogés par catégorie

Prenez un moment pour ajouter une méthode GetProductByProductID(productID) à l’aide de la même technique.

Ces requêtes paramétrables peuvent être testées directement à partir du Concepteur DataSet. Cliquez avec le bouton droit sur la méthode dans TableAdapter et choisissez Aperçu des données. Ensuite, entrez les valeurs à utiliser pour les paramètres, puis cliquez sur Aperçu.

Ces produits appartenant à la catégorie Boissons sont affichés

Figure 19 : Ces produits appartenant à la catégorie Boissons sont affichés (cliquez pour afficher l’image de taille complète)

Avec la méthode GetProductsByCategoryID(categoryID) dans notre DAL, nous pouvons maintenant créer une page ASP.NET qui affiche uniquement ces produits dans une catégorie spécifiée. L’exemple suivant montre tous les produits qui se trouvent dans la catégorie Boissons, qui ont un ID de catégorie de 1.

Beverages.asp

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Beverages.aspx.cs"
    Inherits="Beverages" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h2>Beverages</h2>
        <p>
            <asp:GridView ID="GridView1" runat="server"
             CssClass="DataWebControlStyle">
               <HeaderStyle CssClass="HeaderStyle" />
               <AlternatingRowStyle CssClass="AlternatingRowStyle" />
            </asp:GridView>
             </p>
    </div>
    </form>
</body>
</html>

Beverages.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindTableAdapters;
public partial class Beverages : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ProductsTableAdapter productsAdapter = new
         ProductsTableAdapter();
        GridView1.DataSource =
          productsAdapter.GetProductsByCategoryID(1);
        GridView1.DataBind();
    }
}

Ces produits dans la catégorie Boissons sont affichés

Figure 20 : Ces produits de la catégorie Boissons sont affichés (cliquez pour afficher l’image de taille complète)

Étape 4 : Insertion, mise à jour et suppression de données

Il existe deux modèles couramment utilisés pour l’insertion, la mise à jour et la suppression de données. Le premier modèle, que j’appellerai le modèle direct de base de données, implique la création de méthodes qui, lorsqu’elles sont appelées, émettent une commande INSERT, UPDATE ou DELETE à la base de données qui fonctionne sur un enregistrement de base de données unique. Ces méthodes sont généralement passées dans une série de valeurs scalaires (entiers, chaînes, booléens, DateTimes, etc.) qui correspondent aux valeurs à insérer, mettre à jour ou supprimer. Par exemple, avec ce modèle pour la table Products, la méthode delete prend un paramètre entier, indiquant le ProductID de l’enregistrement à supprimer, tandis que la méthode insert prend une chaîne pour ProductName, une décimale pour UnitPrice, un entier pour UnitsOnStock, et ainsi de suite.

Chaque demande d’insertion, de mise à jour et de suppression est envoyée immédiatement à la base de données

Figure 21 : Chaque demande d’insertion, de mise à jour et de suppression est envoyée immédiatement à la base de données (cliquez pour afficher l’image de taille complète)

L’autre modèle, auquel je vais faire référence en tant que modèle de mise à jour par lot, consiste à mettre à jour un jeu de données entier, DataTable ou une collection de DataRows dans un appel de méthode. Avec ce modèle, un développeur supprime, insère et modifie DataRows dans un DataTable, puis passe ces DataRows ou DataTable dans une méthode de mise à jour. Cette méthode énumère ensuite les DataRows passées, détermine si elles ont été modifiées, ajoutées ou supprimées (via la valeur de propriété RowState de DataRow) et émet la demande de base de données appropriée pour chaque enregistrement.

Toutes les modifications sont synchronisées avec la base de données lorsque la méthode de mise à jour est appelée

Figure 22 : Toutes les modifications sont synchronisées avec la base de données lorsque la méthode de mise à jour est appelée (cliquez pour afficher l’image de taille complète)

TableAdapter utilise le modèle de mise à jour par lot par défaut, mais prend également en charge le modèle direct de base de données. Étant donné que nous avons sélectionné l’option « Générer des instructions Insert, Update et Delete » dans les propriétés avancées lors de la création de notre TableAdapter, productsTableAdapter contient une méthode Update(), qui implémente le modèle de mise à jour par lots. Plus précisément, TableAdapter contient une méthode Update() qui peut être transmise à l’ensemble de données typé, à un DataTable fortement typé ou à un ou plusieurs DataRows. Si vous avez laissé la case à cocher « GenerateDBDirectMethods » cochée lors de la création de TableAdapter, le modèle direct de base de données sera également implémenté via les méthodes Insert(), Update()et Delete().

Les deux modèles de modification de données utilisent les propriétés InsertCommand, UpdateCommand et DeleteCommand de TableAdapter pour émettre leurs commandes INSERT, UPDATE et DELETE dans la base de données. Vous pouvez inspecter et modifier les propriétés InsertCommand, UpdateCommand et DeleteCommand en cliquant sur TableAdapter dans le Concepteur DataSet, puis en accédant au Fenêtre Propriétés. (Vérifiez que vous avez sélectionné TableAdapter et que le L’objet ProductsTableAdapter est celui sélectionné dans la liste déroulante de la Fenêtre Propriétés.)

TableAdapter possède des propriétés InsertCommand, UpdateCommand et DeleteCommand

Figure 23 : TableAdapter possède des propriétés InsertCommand, UpdateCommand et DeleteCommand (cliquez pour afficher l’image de taille complète)

Pour examiner ou modifier l’une de ces propriétés de commande de base de données, cliquez sur la sous-propriété CommandText , qui affiche le Générateur de requêtes.

Configurer les instructions INSERT, UPDATE et DELETE dans le Générateur de requêtes

Figure 24 : Configurer les instructions INSERT, UPDATE et DELETE dans le Générateur de requêtes (Cliquez pour afficher l’image de taille complète)

L’exemple de code suivant montre comment utiliser le modèle de mise à jour par lots pour doubler le prix de tous les produits qui ne sont pas abandonnés et qui ont 25 unités en stock ou moins :

NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
  new NorthwindTableAdapters.ProductsTableAdapter();
// For each product, double its price if it is not discontinued and
// there are 25 items in stock or less
Northwind.ProductsDataTable products = productsAdapter.GetProducts();
foreach (Northwind.ProductsRow product in products)
   if (!product.Discontinued && product.UnitsInStock <= 25)
      product.UnitPrice *= 2;
// Update the products
productsAdapter.Update(products);

Le code ci-dessous montre comment utiliser le modèle direct de base de données pour supprimer par programme un produit particulier, puis en mettre à jour un, puis en ajouter un nouveau :

NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
    new NorthwindTableAdapters.ProductsTableAdapter();
// Delete the product with ProductID 3
productsAdapter.Delete(3);
// Update Chai (ProductID of 1), setting the UnitsOnOrder to 15
productsAdapter.Update("Chai", 1, 1, "10 boxes x 20 bags",
  18.0m, 39, 15, 10, false, 1);
// Add a new product
productsAdapter.Insert("New Product", 1, 1,
  "12 tins per carton", 14.95m, 15, 0, 10, false);

Création de méthodes Insert, Update et Delete personnalisées

Les méthodes Insert(),Update()et Delete() créées par la méthode directe de base de données peuvent être un peu fastidieuses, en particulier pour les tables avec de nombreuses colonnes. En examinant l’exemple de code précédent, sans l’aide d’IntelliSense, il n’est pas particulièrement clair ce que la colonne de table Products mappe à chaque paramètre d’entrée aux méthodes Update() et Insert(). Il peut arriver que nous souhaitions mettre à jour une seule colonne ou deux, ou si vous souhaitez une méthode Insert() personnalisée qui retournera peut-être la valeur du champ IDENTITY (incrément automatique) de l’enregistrement nouvellement inséré.

Pour créer une telle méthode personnalisée, revenez au Concepteur DataSet. Cliquez avec le bouton droit sur TableAdapter et choisissez Ajouter une requête, en retournant à l’Assistant TableAdapter. Sur le deuxième écran, nous pouvons indiquer le type de requête à créer. Créons une méthode qui ajoute un nouveau produit, puis retourne la valeur du ProductID de l’enregistrement nouvellement ajouté. Par conséquent, choisissez de créer une requête INSERT .

Créer une méthode pour ajouter une nouvelle ligne à la table Products

Figure 25 : Créer une méthode pour ajouter une nouvelle ligne à la table Produits (cliquez pour afficher l’image de taille complète)

Dans l’écran suivant, le CommandText d’InsertCommand s’affiche. Augmentez cette requête en ajoutant SELECT SCOPE_IDENTITY() à la fin de la requête, ce qui retourne la dernière valeur d’identité insérée dans une colonne IDENTITY dans la même étendue. (Consultez la documentation technique pour plus d’informations sur SCOPE_IDENTITY() et pourquoi vous souhaitez probablement utiliser SCOPE_IDENTITY() au lieu de @@IDENTITY.) Veillez à mettre fin à l’instruction INSERT avec un point-virgule avant d’ajouter l’instruction SELECT .

Augmenter la requête pour retourner la valeur SCOPE_IDENTITY()

Figure 26 : Augmenter la requête pour renvoyer la valeur SCOPE_IDENTITY() (Cliquer pour afficher l’image de taille complète)

Enfin, nommez la nouvelle méthode InsertProduct.

Définir le nom de la nouvelle méthode sur InsertProduct

Figure 27 : Définir le nom de la nouvelle méthode sur InsertProduct (cliquez pour afficher l’image de taille complète)

Lorsque vous revenez au Concepteur DataSet, vous verrez que ProductsTableAdapter contient une nouvelle méthode, InsertProduct. Si cette nouvelle méthode n’a pas de paramètre pour chaque colonne de la table Products , vous avez oublié d’arrêter l’instruction INSERT avec un point-virgule. Configurez la méthode InsertProduct et vérifiez que vous disposez d’un point-virgule limitant les instructions INSERT et SELECT .

Par défaut, les méthodes insert émettent des méthodes non-requête, ce qui signifie qu’elles retournent le nombre de lignes affectées. Toutefois, nous voulons que la méthode InsertProduct retourne la valeur retournée par la requête, et non le nombre de lignes affectées. Pour ce faire, ajustez la propriété ExecuteMode de la méthode InsertProduct à Scalar.

Remplacez la propriété ExecuteMode par Scalar

Figure 28 : Modifier la propriété ExecuteMode en Scalar (Cliquez pour afficher l’image de taille complète)

Le code suivant montre cette nouvelle méthode InsertProduct en action :

NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
    new NorthwindTableAdapters.ProductsTableAdapter();
// Add a new product
int new_productID = Convert.ToInt32(productsAdapter.InsertProduct
    ("New Product", 1, 1, "12 tins per carton", 14.95m, 10, 0, 10, false));
// On second thought, delete the product
productsAdapter.Delete(new_productID);

Étape 5 : Fin de la couche d’accès aux données

Notez que la classe ProductsTableAdapters retourne les valeurs CategoryID et SupplierID de la table Products , mais n’inclut pas la colonne CategoryName de la table Categories ou la colonne CompanyName de la table Fournisseurs , bien qu’il s’agit probablement des colonnes que nous voulons afficher lors de l’affichage des informations sur le produit. Nous pouvons augmenter la méthode initiale de TableAdapter, GetProducts(), pour inclure les valeurs de colonne CategoryName et CompanyName, qui met également à jour le DataTable fortement typé pour inclure ces nouvelles colonnes.

Cela peut poser un problème, cependant, car les méthodes de TableAdapter pour l’insertion, la mise à jour et la suppression de données sont basées sur cette méthode initiale. Heureusement, les méthodes générées automatiquement pour l’insertion, la mise à jour et la suppression ne sont pas affectées par les sous-requêtes dans la clause SELECT . En prenant soin d’ajouter nos requêtes aux catégories et fournisseurs en tant que sous-requêtes, plutôt que JOIN, nous n’aurons pas à retravailler ces méthodes pour modifier les données. Cliquez avec le bouton droit sur la méthode GetProducts() dans ProductsTableAdapter , puis choisissez Configurer. Ensuite, ajustez la clause SELECT pour qu’elle ressemble à ceci :

SELECT     ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,
(SELECT CategoryName FROM Categories
WHERE Categories.CategoryID = Products.CategoryID) as CategoryName,
(SELECT CompanyName FROM Suppliers
WHERE Suppliers.SupplierID = Products.SupplierID) as SupplierName
FROM         Products

Mettre à jour l’instruction SELECT pour la méthode GetProducts()

Figure 29 : Mettre à jour l’instruction SELECT pour la méthode GetProducts() (Click to view full-size image)

Après avoir mis à jour la méthode GetProducts() pour utiliser cette nouvelle requête, DataTable inclut deux nouvelles colonnes : CategoryName et SupplierName.

DataTable products a deux nouvelles colonnes

Figure 30 : La table de données produits comporte deux nouvelles colonnes

Prenez un moment pour mettre à jour la clause SELECT dans la méthode GetProductsByCategoryID(categoryID) ainsi.

Si vous mettez à jour getProducts () SELECT à l’aide de la syntaxe JOIN , le Concepteur DataSet ne pourra pas générer automatiquement les méthodes d’insertion, de mise à jour et de suppression de données de base de données à l’aide du modèle direct de base de données. Au lieu de cela, vous devrez les créer manuellement comme nous l’avons fait avec la méthode InsertProduct précédemment dans ce tutoriel. En outre, vous devez fournir manuellement les valeurs de propriété InsertCommand, UpdateCommand et DeleteCommand si vous souhaitez utiliser le modèle de mise à jour par lots.

Ajout des TableAdapters restants

Jusqu’à présent, nous n’avons examiné que l’utilisation d’une table TableAdapter unique pour une seule table de base de données. Toutefois, la base de données Northwind contient plusieurs tables associées avec lesquelles nous devons travailler dans notre application web. Un DataSet typé peut contenir plusieurs DataTables associés. Par conséquent, pour terminer notre DAL, nous devons ajouter des DataTables pour les autres tables que nous utiliserons dans ces didacticiels. Pour ajouter un nouveau TableAdapter à un Jeu de données typé, ouvrez le Concepteur DataSet, cliquez avec le bouton droit dans le Concepteur, puis choisissez Ajouter /TableAdapter. Cela crée un DataTable et TableAdapter et vous guide tout au long de l’Assistant que nous avons examiné précédemment dans ce tutoriel.

Prenez quelques minutes pour créer les TablesAdapters et méthodes suivantes à l’aide des requêtes suivantes. Notez que les requêtes dans ProductsTableAdapter incluent les sous-requêtes pour saisir les noms des fournisseurs et des catégories de chaque produit. En outre, si vous avez suivi, vous avez déjà ajouté les méthodes GetProducts() et GetProductsByCategoryID() de la classe ProductsTableAdapter.

  • ProductsTableAdapter

    • GetProducts :

      SELECT     ProductID, ProductName, SupplierID, 
      CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, 
      UnitsOnOrder, ReorderLevel, Discontinued, 
      (SELECT CategoryName FROM Categories WHERE
      Categories.CategoryID = Products.CategoryID) as 
      CategoryName, (SELECT CompanyName FROM Suppliers
      WHERE Suppliers.SupplierID = Products.SupplierID) 
      as SupplierName
      FROM         Products
      
    • GetProductsByCategoryID :

      SELECT     ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued, (SELECT CategoryName
      FROM Categories WHERE Categories.CategoryID = 
      Products.CategoryID) as CategoryName,
      (SELECT CompanyName FROM Suppliers WHERE
      Suppliers.SupplierID = Products.SupplierID)
      as SupplierName
      FROM         Products
      WHERE      CategoryID = @CategoryID
      
    • GetProductsBySupplierID :

      SELECT     ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued, (SELECT CategoryName
      FROM Categories WHERE Categories.CategoryID = 
      Products.CategoryID) as CategoryName, 
      (SELECT CompanyName FROM Suppliers WHERE 
      Suppliers.SupplierID = Products.SupplierID) as SupplierName
      FROM         Products
      WHERE SupplierID = @SupplierID
      
    • GetProductByProductID :

      SELECT     ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued, (SELECT CategoryName 
      FROM Categories WHERE Categories.CategoryID = 
      Products.CategoryID) as CategoryName, 
      (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) 
      as SupplierName
      FROM         Products
      WHERE ProductID = @ProductID
      
  • CategoriesTableAdapter

    • GetCategories :

      SELECT     CategoryID, CategoryName, Description
      FROM         Categories
      
    • GetCategoryByCategoryID :

      SELECT     CategoryID, CategoryName, Description
      FROM         Categories
      WHERE CategoryID = @CategoryID
      
  • SuppliersTableAdapter

    • GetSuppliers :

      SELECT     SupplierID, CompanyName, Address,
      City, Country, Phone
      FROM         Suppliers
      
    • GetSuppliersByCountry :

      SELECT     SupplierID, CompanyName, Address,
      City, Country, Phone
      FROM         Suppliers
      WHERE Country = @Country
      
    • GetSupplierBySupplierID :

      SELECT     SupplierID, CompanyName, Address,
      City, Country, Phone
      FROM         Suppliers
      WHERE SupplierID = @SupplierID
      
  • EmployeesTableAdapter

    • GetEmployees :

      SELECT     EmployeeID, LastName, FirstName, Title,
      HireDate, ReportsTo, Country
      FROM         Employees
      
    • GetEmployeesByManager :

      SELECT     EmployeeID, LastName, FirstName, Title, 
      HireDate, ReportsTo, Country
      FROM         Employees
      WHERE ReportsTo = @ManagerID
      
    • GetEmployeeByEmployeeID :

      SELECT     EmployeeID, LastName, FirstName, Title,
      HireDate, ReportsTo, Country
      FROM         Employees
      WHERE EmployeeID = @EmployeeID
      

Concepteur DataSet après l’ajout des quatre TableAdapters

Figure 31 : Concepteur DataSet après l’ajout des quatre TableAdapters (cliquez pour afficher l’image de taille complète)

Ajout de code personnalisé à la dal

Les TableAdapters et DataTables ajoutés au DataSet typé sont exprimés sous la forme d’un fichier de définition de schéma XML (Northwind.xsd). Vous pouvez afficher ces informations de schéma en cliquant avec le bouton droit sur le fichier Northwind.xsd dans le Explorateur de solutions et en choisissant Afficher le code.

Fichier XSD (XML Schema Definition) pour l’ensemble de données typé Northwinds

Figure 32 : Fichier XSD (XML Schema Definition) pour l’ensemble de données typé Northwinds (Cliquez pour afficher l’image de taille complète)

Ces informations de schéma sont traduites en code C# ou Visual Basic au moment du design lors de la compilation ou au moment de l’exécution (si nécessaire), à quel moment vous pouvez le parcourir avec le débogueur. Pour afficher ce code généré automatiquement, accédez à l’affichage de classes et explorez les classes TableAdapter ou Typed DataSet. Si vous ne voyez pas l’affichage classe sur votre écran, accédez au menu Affichage et sélectionnez-le à partir de là, ou appuyez sur Ctrl+Maj+C. À partir de l’affichage de classes, vous pouvez voir les propriétés, les méthodes et les événements des classes Typed DataSet et TableAdapter. Pour afficher le code d’une méthode particulière, double-cliquez sur le nom de la méthode dans l’affichage de classes ou cliquez dessus avec le bouton droit, puis choisissez Atteindre la définition.

Inspecter le code généré automatiquement en sélectionnant Atteindre la définition à partir de l’affichage de classes

Figure 33 : Inspecter le code généré automatiquement en sélectionnant Atteindre la définition dans l’affichage de classes

Même si le code généré automatiquement peut être un excellent économiseur de temps, le code est souvent très générique et doit être personnalisé pour répondre aux besoins uniques d’une application. Toutefois, le risque d’étendre le code généré automatiquement est que l’outil qui a généré le code peut décider qu’il est temps de « régénérer » et de remplacer vos personnalisations. Avec le nouveau concept de classe partielle de .NET 2.0, il est facile de fractionner une classe sur plusieurs fichiers. Cela nous permet d’ajouter nos propres méthodes, propriétés et événements aux classes générées automatiquement sans avoir à vous soucier de l’écriture de nos personnalisations par Visual Studio.

Pour montrer comment personnaliser le DAL, nous allons ajouter une méthode GetProducts() à la classe SuppliersRow . La classe SuppliersRow représente un enregistrement unique dans la table Fournisseurs ; chaque fournisseur peut fournir zéro à de nombreux produits, donc GetProducts() retournera ces produits du fournisseur spécifié. Pour ce faire, créez un fichier de classe dans le dossier App_Code nommé SuppliersRow.cs et ajoutez le code suivant :

using System;
using System.Data;
using NorthwindTableAdapters;
public partial class Northwind
{
    public partial class SuppliersRow
    {
        public Northwind.ProductsDataTable GetProducts()
        {
            ProductsTableAdapter productsAdapter =
             new ProductsTableAdapter();
            return
              productsAdapter.GetProductsBySupplierID(this.SupplierID);
        }
    }
}

Cette classe partielle indique au compilateur que lors de la génération de la classe Northwind.SuppliersRow pour inclure la méthode GetProducts() que nous venons de définir. Si vous générez votre projet, puis revenez à la vue de classe, vous verrez GetProducts() maintenant répertorié comme méthode de Northwind.SuppliersRow.

La méthode GetProducts() fait maintenant partie de la classe Northwind.SuppliersRow

Figure 34 : La méthode GetProducts() fait maintenant partie de la classe Northwind.SuppliersRow

La méthode GetProducts() peut désormais être utilisée pour énumérer l’ensemble de produits pour un fournisseur particulier, comme le montre le code suivant :

NorthwindTableAdapters.SuppliersTableAdapter suppliersAdapter =
    new NorthwindTableAdapters.SuppliersTableAdapter();
// Get all of the suppliers
Northwind.SuppliersDataTable suppliers =
  suppliersAdapter.GetSuppliers();
// Enumerate the suppliers
foreach (Northwind.SuppliersRow supplier in suppliers)
{
    Response.Write("Supplier: " + supplier.CompanyName);
    Response.Write("<ul>");
    // List the products for this supplier
    Northwind.ProductsDataTable products = supplier.GetProducts();
    foreach (Northwind.ProductsRow product in products)
        Response.Write("<li>" + product.ProductName + "</li>");
    Response.Write("</ul><p> </p>");
}

Ces données peuvent également être affichées dans n’importe quel ASP. Contrôles Web de données de NET. La page suivante utilise un contrôle GridView avec deux champs :

  • BoundField qui affiche le nom de chaque fournisseur et
  • TemplateField qui contient un contrôle BulletedList lié aux résultats retournés par la méthode GetProducts() pour chaque fournisseur.

Nous allons examiner comment afficher ces rapports maître-détail dans les didacticiels futurs. Pour l’instant, cet exemple est conçu pour illustrer l’utilisation de la méthode personnalisée ajoutée à la classe Northwind.SuppliersRow .

SuppliersAndProducts.aspx

<%@ Page Language="C#" CodeFile="SuppliersAndProducts.aspx.cs"
    AutoEventWireup="true" Inherits="SuppliersAndProducts" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h2>
            Suppliers and Their Products</h2>
        <p>
            <asp:GridView ID="GridView1" runat="server"
             AutoGenerateColumns="False"
             CssClass="DataWebControlStyle">
                <HeaderStyle CssClass="HeaderStyle" />
                <AlternatingRowStyle CssClass="AlternatingRowStyle" />
                <Columns>
                    <asp:BoundField DataField="CompanyName"
                      HeaderText="Supplier" />
                    <asp:TemplateField HeaderText="Products">
                        <ItemTemplate>
                            <asp:BulletedList ID="BulletedList1"
                             runat="server" DataSource="<%# ((Northwind.SuppliersRow) ((System.Data.DataRowView) Container.DataItem).Row).GetProducts() %>"
                                 DataTextField="ProductName">
                            </asp:BulletedList>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
             </p>
    </div>
    </form>
</body>
</html>

SuppliersAndProducts.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindTableAdapters;
public partial class SuppliersAndProducts : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        SuppliersTableAdapter suppliersAdapter = new
          SuppliersTableAdapter();
        GridView1.DataSource = suppliersAdapter.GetSuppliers();
        GridView1.DataBind();
    }
}

Le nom de la société du fournisseur est répertorié dans la colonne gauche, leurs produits à droite

Figure 35 : Le nom de la société du fournisseur est répertorié dans la colonne gauche, leurs produits dans la droite (cliquez pour afficher l’image de taille complète)

Résumé

Lors de la création d’une application web créant le DAL doit être l’une de vos premières étapes, se produisant avant de commencer à créer votre couche de présentation. Avec Visual Studio, la création d’un DAL basé sur des jeux de données typés est une tâche qui peut être effectuée en 10 à 15 minutes sans écrire de ligne de code. Les didacticiels en cours s’appuient sur ce DAL. Dans le tutoriel suivant, nous allons définir un certain nombre de règles métier et voir comment les implémenter dans une couche logique métier distincte.

Bonne programmation !

Pour aller plus loin

Pour plus d’informations sur les sujets abordés dans ce tutoriel, consultez les ressources suivantes :

Formation vidéo sur les rubriques contenues dans ce didacticiel

À propos de l’auteur

Scott Mitchell, auteur de sept livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies Web Microsoft depuis 1998. Scott travaille en tant que consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 en 24 heures. Il peut être accessible à mitchell@4GuysFromRolla.com. ou via son blog, qui peut être trouvé à http://ScottOnWriting.NET.

Merci spécial à

Cette série de tutoriels a été examinée par de nombreux réviseurs utiles. Les réviseurs principaux de ce tutoriel étaient Ron Green, Hilton Giesenow, Dennis Patterson, Liz Shulok, Abel Gomez et Carlos Santos. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.