Partager via


Mise à jour du TableAdapter pour l’utilisation de jointures (VB)

par Scott Mitchell

Télécharger le PDF

Lorsque vous utilisez une base de données, il est courant de demander des données réparties sur plusieurs tables. Pour récupérer des données de deux tables différentes, nous pouvons utiliser une sous-requête corrélée ou une opération JOIN. Dans ce tutoriel, nous comparons les sous-requêtes corrélées et la syntaxe JOIN avant de voir comment créer un TableAdapter qui inclut un JOIN dans sa requête main.

Introduction

Avec les bases de données relationnelles, les données qui nous intéressent sont souvent réparties sur plusieurs tables. Par exemple, lorsque vous affichez des informations sur le produit, nous voulons probablement répertorier chaque catégorie de produit correspondante et les noms de fournisseurs. La Products table a CategoryID des valeurs et SupplierID , mais les noms de catégorie et de fournisseur réels se trouvent dans les Categories tables et Suppliers , respectivement.

Pour récupérer des informations à partir d’une autre table associée, nous pouvons utiliser des sous-requêtes corrélées ou JOINdes. Une sous-requête corrélée est une requête imbriquée SELECT qui référence des colonnes dans la requête externe. Par exemple, dans le didacticiel Création d’une couche d’accès aux données, nous avons utilisé deux sous-requêtes corrélées dans la ProductsTableAdapter requête s main pour retourner les noms de catégorie et de fournisseur pour chaque produit. Un JOIN est une construction SQL qui fusionne les lignes associées à partir de deux tables différentes. Nous avons utilisé un JOIN dans le didacticiel Interrogation des données avec le contrôle SqlDataSource pour afficher les informations de catégorie en même temps que chaque produit.

La raison pour laquelle nous nous sommes abstenus d’utiliser JOIN des avec Les TableAdapters est due aux limitations de l’Assistant TableAdapter pour générer automatiquement les instructions , UPDATEet DELETE correspondantesINSERT. Plus précisément, si la requête TableAdapter s main contient JOIN des s, tableAdapter ne peut pas créer automatiquement les instructions SQL ad hoc ou les procédures stockées pour ses InsertCommandpropriétés , UpdateCommandet DeleteCommand .

Dans ce tutoriel, nous allons brièvement comparer les sous-requêtes corrélées et JOIN les sous-requêtes avant d’explorer comment créer un TableAdapter qui inclut JOIN des dans sa requête main.

Comparaison et contraste des sous-requêtes corrélées etJOIN des

Rappelez-vous que le ProductsTableAdapter créé dans le premier tutoriel du Northwind DataSet utilise des sous-requêtes corrélées pour ramener la catégorie et le nom de fournisseur correspondants de chaque produit. La ProductsTableAdapter requête s main est illustrée ci-dessous.

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

Les deux sous-requêtes corrélées ( (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID) et ) sont SELECT des requêtes qui retournent une valeur unique par produit en tant que colonne supplémentaire dans la liste des colonnes de l’instruction externe SELECT(SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) .

Vous pouvez également utiliser un JOIN pour renvoyer le nom du fournisseur et de la catégorie de chaque produit. La requête suivante retourne la même sortie que celle ci-dessus, mais utilise JOIN s à la place des sous-requêtes :

SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       Categories.CategoryName, 
       Suppliers.CompanyName as SupplierName
FROM Products
    LEFT JOIN Categories ON
        Categories.CategoryID = Products.CategoryID
    LEFT JOIN Suppliers ON
        Suppliers.SupplierID = Products.SupplierID

Un JOIN fusionne les enregistrements d’une table avec les enregistrements d’une autre table en fonction de certains critères. Dans la requête ci-dessus, par exemple, indique LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID SQL Server de fusionner chaque enregistrement de produit avec l’enregistrement de catégorie dont CategoryID la valeur correspond à la valeur du CategoryID produit. Le résultat fusionné nous permet d’utiliser les champs de catégorie correspondants pour chaque produit (par CategoryNameexemple).

Notes

JOIN s sont couramment utilisés lors de l’interrogation de données à partir de bases de données relationnelles. Si vous débutez avec la JOIN syntaxe ou si vous avez besoin d’en faire un peu plus sur son utilisation, je vous recommande le didacticiel De jointure SQL à W3 Schools. Les sections Notions de base et Notions de base des sous-requêtes de la documentation en ligne de SQL sont également à lireJOIN.

Étant donné que JOIN s et les sous-requêtes corrélées peuvent tous deux être utilisés pour récupérer des données associées à partir d’autres tables, de nombreux développeurs se grattent la tête et se demandent quelle approche utiliser. Tous les gourous SQL auxquels j’ai parlé ont dit à peu près la même chose, qu’il n’est pas vraiment important pour les performances, car SQL Server produira des plans d’exécution à peu près identiques. Leur conseil, alors, est d’utiliser la technique que vous et votre équipe êtes le plus à l’aise avec. Il est à noter qu’après avoir donné cet avis, ces experts expriment immédiatement leur préférence pour les JOIN sous-requêtes corrélées.

Lors de la génération d’une couche d’accès aux données à l’aide de DataSets typés, les outils fonctionnent mieux lors de l’utilisation de sous-requêtes. En particulier, l’Assistant TableAdapter ne génère pas automatiquement les instructions , UPDATEet DELETE correspondantes INSERTsi la requête main contient JOIN des s, mais génère automatiquement ces instructions lorsque des sous-requêtes corrélées sont utilisées.

Pour explorer cette lacune, créez un dataset temporaire typé dans le ~/App_Code/DAL dossier . Pendant l’Assistant Configuration de TableAdapter, choisissez d’utiliser des instructions SQL ad hoc et entrez la requête suivante SELECT (voir la figure 1) :

SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       Categories.CategoryName, 
       Suppliers.CompanyName as SupplierName
FROM Products
    LEFT JOIN Categories ON
        Categories.CategoryID = Products.CategoryID
    LEFT JOIN Suppliers ON
        Suppliers.SupplierID = Products.SupplierID

Capture d’écran montrant la fenêtre Assistant Configuration de TableAdaptor avec une requête entrée qui contient des JOIN.

Figure 1 : Entrer une requête principale qui contient JOIN des (cliquer pour afficher l’image en taille réelle)

Par défaut, l’objet TableAdapter crée INSERTautomatiquement des instructions , UPDATEet DELETE basées sur la requête main. Si vous cliquez sur le bouton Avancé, vous pouvez voir que cette fonctionnalité est activée. Malgré ce paramètre, TableAdapter ne peut pas créer les INSERTinstructions , UPDATEetDELETE, car la requête main contient un JOIN.

Capture d’écran montrant la fenêtre Options avancées avec la case à cocher Générer des instructions Insérer, Mettre à jour et Supprimer sélectionnée.

Figure 2 : Entrer une requête principale qui contient JOIN des

Cliquez sur Terminer pour terminer l'Assistant. À ce stade, votre dataset Designer inclut un Seul TableAdapter avec un DataTable avec des colonnes pour chacun des champs retournés dans la liste des colonnes de la SELECT requête. Cela inclut et , comme le montre la CategoryNameSupplierNamefigure 3.

Le DataTable inclut une colonne pour chaque champ retourné dans la liste de colonnes

Figure 3 : Le DataTable inclut une colonne pour chaque champ retourné dans la liste des colonnes

Bien que le DataTable ait les colonnes appropriées, l’objet TableAdapter n’a pas de valeurs pour ses InsertCommandpropriétés , UpdateCommandet DeleteCommand . Pour confirmer cela, cliquez sur TableAdapter dans le Designer, puis accédez à la Fenêtre Propriétés. Vous verrez que les InsertCommandpropriétés , UpdateCommandet DeleteCommand sont définies sur (Aucun).

Les propriétés InsertCommand, UpdateCommand et DeleteCommand sont définies sur (Aucun)

Figure 4 : Les InsertCommandpropriétés , UpdateCommandet DeleteCommand sont définies sur (Aucune) (Cliquez pour afficher l’image en taille réelle)

Pour contourner cette lacune, nous pouvons fournir manuellement les instructions et paramètres SQL pour les InsertCommandpropriétés , UpdateCommandet DeleteCommand via le Fenêtre Propriétés. Nous pouvons également commencer par configurer la requête main TableAdapter pour qu’elle n’inclue aucunJOIN s. Cela permet aux INSERTinstructions , UPDATEet DELETE d’être générées automatiquement pour nous. Une fois l’Assistant terminé, nous pouvons ensuite mettre à jour manuellement tableAdapter à SelectCommand partir du Fenêtre Propriétés afin qu’il inclue la JOIN syntaxe.

Bien que cette approche fonctionne, elle est très fragile lors de l’utilisation de requêtes SQL ad hoc, car chaque fois que la requête main TableAdapter est reconfigurée via l’Assistant, les instructions , UPDATEet DELETE générées INSERTautomatiquement sont recréées. Cela signifie que toutes les personnalisations que nous avons effectuées par la suite seraient perdues si nous cliquions avec le bouton droit sur TableAdapter, si nous choisissions Configurer dans le menu contextuel et si nous réécutions l’Assistant.

La fragilité des instructions , UPDATEet DELETE générées INSERTautomatiquement par TableAdapter est, heureusement, limitée aux instructions SQL ad hoc. Si votre TableAdapter utilise des procédures stockées, vous pouvez personnaliser les SelectCommandprocédures stockées , InsertCommand, UpdateCommandou DeleteCommand et réexécuter l’Assistant Configuration de TableAdapter sans avoir à craindre que les procédures stockées soient modifiées.

Au cours des étapes suivantes, nous allons créer un Objet TableAdapter qui, initialement, utilise une requête main qui omet de s JOIN afin que les procédures stockées d’insertion, de mise à jour et de suppression correspondantes soient générées automatiquement. Nous allons ensuite mettre à jour pour qu’utilise SelectCommand un JOIN qui retourne des colonnes supplémentaires à partir de tables associées. Enfin, nous allons créer une classe de couche de logique métier correspondante et illustrer l’utilisation de TableAdapter dans une page web ASP.NET.

Étape 1 : Création de TableAdapter à l’aide d’une requête principale simplifiée

Pour ce tutoriel, nous allons ajouter un TableAdapter et un DataTable fortement typé pour la Employees table dans le NorthwindWithSprocs DataSet. La Employees table contient un ReportsTo champ qui a spécifié le EmployeeID du responsable de l’employé. Par exemple, l’employée Anne Dodsworth a une ReportTo valeur de 5, qui est la EmployeeID valeur de Steven Buchanan. Par conséquent, Anne rend compte à Steven, son manager. En plus de signaler la valeur de ReportsTo chaque employé, nous pouvons également récupérer le nom de son responsable. Cela peut être effectué à l’aide d’un JOIN. Toutefois, l’utilisation d’un JOIN lors de la création initiale de TableAdapter empêche l’Assistant de générer automatiquement les fonctionnalités d’insertion, de mise à jour et de suppression correspondantes. Par conséquent, nous allons commencer par créer un TableAdapter dont main requête ne contient pas JOIN de s. Ensuite, à l’étape 2, nous allons mettre à jour la procédure stockée de requête main pour récupérer le nom du gestionnaire via un JOIN.

Commencez par ouvrir le NorthwindWithSprocs DataSet dans le ~/App_Code/DAL dossier . Cliquez avec le bouton droit sur le Designer, sélectionnez l’option Ajouter dans le menu contextuel, puis sélectionnez l’élément de menu TableAdapter. L’Assistant Configuration de TableAdapter est alors lancé. Comme le montre la figure 5, demandez à l’Assistant de créer de nouvelles procédures stockées, puis cliquez sur Suivant. Pour plus d’informations sur la création de procédures stockées à partir de l’Assistant TableAdapter, consultez le didacticiel Création de nouvelles procédures stockées pour le dataset typé TableAdapters .

Sélectionnez l’option Créer des procédures stockées.

Figure 5 : Sélectionnez l’option Créer des procédures stockées (cliquer pour afficher l’image en taille réelle)

Utilisez l’instruction suivante SELECT pour la requête main TableAdapter :

SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees

Étant donné que cette requête n’inclut pas JOIN de s, l’Assistant TableAdapter crée automatiquement des procédures stockées avec les instructions , UPDATEet DELETE correspondantesINSERT, ainsi qu’une procédure stockée pour l’exécution de la requête main.

L’étape suivante nous permet de nommer les procédures stockées de TableAdapter. Utilisez les noms Employees_Select, Employees_Insert, Employees_Updateet Employees_Delete, comme illustré dans la figure 6.

Nommez les procédures stockées de TableAdapter

Figure 6 : Nommez les procédures stockées de TableAdapter (cliquez pour afficher l’image en taille réelle)

La dernière étape nous invite à nommer les méthodes TableAdapter. Utilisez Fill et GetEmployees comme noms de méthode. Veillez également à cocher Créer des méthodes pour envoyer des mises à jour directement à la base de données (GenerateDBDirectMethods) cochée.

Nommez les méthodes Fill et GetEmployees tableAdapter

Figure 7 : Nommez les méthodes Fill TableAdapter et GetEmployees (Cliquez pour afficher l’image en taille réelle)

Après avoir terminé l’Assistant, prenez un moment pour examiner les procédures stockées dans la base de données. Vous devez voir quatre nouveaux : Employees_Select, Employees_Insert, Employees_Updateet Employees_Delete. Ensuite, inspectez le EmployeesDataTable et EmployeesTableAdapter vient de créer. DataTable contient une colonne pour chaque champ retourné par la requête main. Cliquez sur TableAdapter, puis accédez au Fenêtre Propriétés. Vous verrez que les InsertCommandpropriétés , UpdateCommandet DeleteCommand sont correctement configurées pour appeler les procédures stockées correspondantes.

TableAdapter inclut des fonctionnalités d’insertion, de mise à jour et de suppression

Figure 8 : La tableAdapter inclut des fonctionnalités d’insertion, de mise à jour et de suppression (cliquer pour afficher l’image en taille réelle)

Avec les procédures stockées d’insertion, de mise à jour et de suppression automatiquement créées et les InsertCommandpropriétés , UpdateCommandet DeleteCommand correctement configurées, nous sommes prêts à personnaliser la SelectCommand procédure stockée s pour retourner des informations supplémentaires sur chaque responsable de chaque employé. Plus précisément, nous devons mettre à jour la Employees_Select procédure stockée pour utiliser un JOIN et retourner les valeurs et LastName les valeurs du FirstName gestionnaire. Une fois la procédure stockée mise à jour, nous devons mettre à jour le DataTable afin qu’il inclue ces colonnes supplémentaires. Nous aborderons ces deux tâches aux étapes 2 et 3.

Étape 2 : Personnalisation de la procédure stockée pour inclure unJOIN

Commencez par atteindre le Explorer serveur, puis explorez le dossier Procédures stockées de la base de données Northwind, puis ouvrez la Employees_Select procédure stockée. Si vous ne voyez pas cette procédure stockée, cliquez avec le bouton droit sur le dossier Procédures stockées et choisissez Actualiser. Mettez à jour la procédure stockée afin qu’elle utilise un LEFT JOIN pour retourner le nom et le prénom du gestionnaire :

SELECT Employees.EmployeeID, Employees.LastName, 
       Employees.FirstName, Employees.Title, 
       Employees.HireDate, Employees.ReportsTo, 
       Employees.Country,
       Manager.FirstName as ManagerFirstName, 
       Manager.LastName as ManagerLastName
FROM Employees
    LEFT JOIN Employees AS Manager ON
        Employees.ReportsTo = Manager.EmployeeID

Après avoir mis à jour l’instruction SELECT , enregistrez les modifications en accédant au menu Fichier et en choisissant Enregistrer Employees_Select. Vous pouvez également cliquer sur l’icône Enregistrer dans la barre d’outils ou appuyer sur Ctrl+S. Après avoir enregistré vos modifications, cliquez avec le bouton droit sur la Employees_Select procédure stockée dans le serveur Explorer et choisissez Exécuter. Cette opération exécute la procédure stockée et affiche ses résultats dans la fenêtre Sortie (voir figure 9).

Les résultats des procédures stockées sont affichés dans la fenêtre Sortie

Figure 9 : Les résultats des procédures stockées sont affichés dans la fenêtre Sortie (cliquer pour afficher l’image en taille réelle)

Étape 3 : Mise à jour des colonnes de DataTable

À ce stade, la Employees_Select procédure stockée retourne ManagerFirstName les valeurs et ManagerLastName , mais il EmployeesDataTable manque ces colonnes. Ces colonnes manquantes peuvent être ajoutées au DataTable de deux manières :

  • Manuellement : cliquez avec le bouton droit sur le DataTable dans le DataSet Designer et, dans le menu Ajouter, choisissez Colonne. Vous pouvez ensuite nommer la colonne et définir ses propriétés en conséquence.
  • Automatiquement : l’Assistant Configuration de TableAdapter met à jour les colonnes de DataTable pour refléter les champs retournés par la SelectCommand procédure stockée. Lorsque vous utilisez des instructions SQL ad hoc, l’Assistant supprime également les InsertCommandpropriétés , UpdateCommandet DeleteCommand , car le SelectCommand contient maintenant un JOIN. Toutefois, lors de l’utilisation de procédures stockées, ces propriétés de commande restent intactes.

Nous avons exploré l’ajout manuel de colonnes DataTable dans les tutoriels précédents, notamment Master/Detail Using a Bulleted List of Master Records with a Details DataList and Uploading Files, et nous examinerons ce processus de nouveau plus en détail dans notre prochain tutoriel. Toutefois, pour ce tutoriel, nous allons utiliser l’approche automatique via l’Assistant Configuration de TableAdapter.

Commencez par cliquer avec le bouton droit sur et EmployeesTableAdapter sélectionnez Configurer dans le menu contextuel. Cela fait apparaître l’Assistant Configuration de TableAdapter, qui répertorie les procédures stockées utilisées pour la sélection, l’insertion, la mise à jour et la suppression, ainsi que leurs valeurs et paramètres de retour (le cas échéant). La figure 10 montre cet Assistant. Ici, nous pouvons voir que la Employees_Select procédure stockée retourne désormais les ManagerFirstName champs et ManagerLastName .

L’Assistant affiche la liste de colonnes mise à jour pour la procédure stockée Employees_Select

Figure 10 : L’Assistant affiche la liste des colonnes mises à jour pour la Employees_Select procédure stockée (cliquez pour afficher l’image en taille réelle)

Terminez l’Assistant en cliquant sur Terminer. Lorsque vous revenez à l’Designer DataSet, le EmployeesDataTable inclut deux colonnes supplémentaires : ManagerFirstName et ManagerLastName.

EmployeesDataTable contient deux nouvelles colonnes

Figure 11 : contient EmployeesDataTable deux nouvelles colonnes (cliquer pour afficher l’image en taille réelle)

Pour illustrer que la procédure stockée mise à jour Employees_Select est en vigueur et que les fonctionnalités d’insertion, de mise à jour et de suppression de TableAdapter sont toujours fonctionnelles, créons une page web qui permet aux utilisateurs d’afficher et de supprimer des employés. Toutefois, avant de créer une telle page, nous devons d’abord créer une classe dans la couche logique métier pour travailler avec les employés du NorthwindWithSprocs DataSet. À l’étape 4, nous allons créer une EmployeesBLLWithSprocs classe. À l’étape 5, nous allons utiliser cette classe à partir d’une page ASP.NET.

Étape 4 : Implémentation de la couche logique métier

Créez un fichier de classe dans le ~/App_Code/BLL dossier nommé EmployeesBLLWithSprocs.vb. Cette classe imite la sémantique de la classe existante EmployeesBLL , seule celle-ci fournit moins de méthodes et utilise le NorthwindWithSprocs DataSet (au lieu du Northwind DataSet). Ajoutez le code suivant à la classe EmployeesBLLWithSprocs .

Imports NorthwindWithSprocsTableAdapters
<System.ComponentModel.DataObject()> _
Public Class EmployeesBLLWithSprocs
    Private _employeesAdapter As EmployeesTableAdapter = Nothing
    Protected ReadOnly Property Adapter() As EmployeesTableAdapter
        Get
            If _employeesAdapter Is Nothing Then
                _employeesAdapter = New EmployeesTableAdapter()
            End If
            Return _employeesAdapter
        End Get
    End Property
    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Select, True)> _
    Public Function GetEmployees() As NorthwindWithSprocs.EmployeesDataTable
        Return Adapter.GetEmployees()
    End Function
    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Delete, True)> _
    Public Function DeleteEmployee(ByVal employeeID As Integer) As Boolean
        Dim rowsAffected = Adapter.Delete(employeeID)
        'Return true if precisely one row was deleted, otherwise false
        Return rowsAffected = 1
    End Function
End Class

La EmployeesBLLWithSprocs propriété s de Adapter classe retourne une instance du NorthwindWithSprocs DataSet s EmployeesTableAdapter. Il est utilisé par les méthodes et DeleteEmployee de classe.GetEmployees La GetEmployees méthode appelle la EmployeesTableAdapter méthode s correspondante GetEmployees , qui appelle la Employees_Select procédure stockée et remplit ses résultats dans un EmployeeDataTable. De DeleteEmployee même, la méthode appelle la EmployeesTableAdapter méthode s Delete , qui appelle la Employees_Delete procédure stockée.

Étape 5 : Utilisation des données dans la couche présentation

Une fois la EmployeesBLLWithSprocs classe terminée, nous sommes prêts à utiliser les données des employés via une page ASP.NET. Ouvrez la JOINs.aspx page dans le AdvancedDAL dossier et faites glisser un GridView à partir de la boîte à outils sur le Designer, affectant à sa ID propriété la valeur Employees. Ensuite, à partir de la balise active gridView, liez la grille à un nouveau contrôle ObjectDataSource nommé EmployeesDataSource.

Configurez ObjectDataSource pour utiliser la EmployeesBLLWithSprocs classe et, à partir des onglets SELECT et DELETE, assurez-vous que les GetEmployees méthodes et DeleteEmployee sont sélectionnées dans les listes déroulantes. Cliquez sur Terminer pour terminer la configuration de ObjectDataSource.

Configurer ObjectDataSource pour utiliser la classe EmployeesBLLWithSprocs

Figure 12 : Configurer ObjectDataSource pour utiliser la EmployeesBLLWithSprocs classe (cliquer pour afficher l’image en taille réelle)

Faire en sorte que ObjectDataSource utilise les méthodes GetEmployees et DeleteEmployee

Figure 13 : Faites utiliser les GetEmployees méthodes et DeleteEmployee par ObjectDataSource (cliquez pour afficher l’image en taille réelle)

Visual Studio ajoute un objet BoundField au GridView pour chacune des EmployeesDataTable colonnes s. Supprimez tous ces boundFields à l’exception Titlede , LastName, FirstNameManagerFirstName, et ManagerLastName renommez les HeaderText propriétés des quatre derniers BoundFields en Nom, Prénom, Prénom du Gestionnaire et Nom du Gestionnaire, respectivement.

Pour permettre aux utilisateurs de supprimer des employés de cette page, nous devons effectuer deux opérations. Tout d’abord, demandez à GridView de fournir des fonctionnalités de suppression en cochant l’option Activer la suppression de sa balise active. Deuxièmement, remplacez la propriété ObjectDataSource OldValuesParameterFormatString de la valeur définie par l’Assistant ObjectDataSource (original_{0}) par sa valeur par défaut ({0}). Après avoir apporté ces modifications, votre balisage déclaratif GridView et ObjectDataSource doit ressembler à ce qui suit :

<asp:GridView ID="Employees" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="EmployeeID" DataSourceID="EmployeesDataSource">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" />
        <asp:BoundField DataField="Title" 
            HeaderText="Title" 
            SortExpression="Title" />
        <asp:BoundField DataField="LastName" 
            HeaderText="Last Name" 
            SortExpression="LastName" />
        <asp:BoundField DataField="FirstName" 
            HeaderText="First Name" 
            SortExpression="FirstName" />
        <asp:BoundField DataField="ManagerFirstName" 
            HeaderText="Manager's First Name" 
            SortExpression="ManagerFirstName" />
        <asp:BoundField DataField="ManagerLastName" 
            HeaderText="Manager's Last Name" 
            SortExpression="ManagerLastName" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="EmployeesDataSource" runat="server" 
    DeleteMethod="DeleteEmployee" OldValuesParameterFormatString="{0}" 
    SelectMethod="GetEmployees" TypeName="EmployeesBLLWithSprocs">
    <DeleteParameters>
        <asp:Parameter Name="employeeID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

Testez la page en la visitant via un navigateur. Comme le montre la figure 14, la page répertorie chaque employé et son nom de responsable (en supposant qu’il en a un).

Join dans la procédure stockée Employees_Select retourne le nom du gestionnaire

Figure 14 : JOIN dans la Employees_Select procédure stockée retourne le nom du gestionnaire (cliquez pour afficher l’image en taille réelle)

Cliquez sur le bouton Supprimer pour démarrer le flux de travail de suppression, qui aboutit à l’exécution de la Employees_Delete procédure stockée. Toutefois, la tentative d’instruction DELETE dans la procédure stockée échoue en raison d’une violation de contrainte de clé étrangère (voir figure 15). Plus précisément, chaque employé a un ou plusieurs enregistrements dans la Orders table, ce qui entraîne l’échec de la suppression.

La suppression d’un employé qui a des commandes correspondantes entraîne une violation de contrainte de clé étrangère

Figure 15 : La suppression d’un employé qui a des commandes correspondantes entraîne une violation de contrainte de clé étrangère (cliquez pour afficher l’image en taille réelle)

Pour autoriser la suppression d’un employé, vous pouvez :

  • Mettez à jour la contrainte de clé étrangère pour les suppressions en cascade,
  • Supprimez manuellement les enregistrements de la Orders table pour les employés que vous souhaitez supprimer, ou
  • Mettez à jour la Employees_Delete procédure stockée pour supprimer d’abord les enregistrements associés de la Orders table avant de supprimer l’enregistrement Employees . Nous avons abordé cette technique dans le tutoriel Utilisation de procédures stockées existantes pour le dataset typé s TableAdapters .

Je laisse cela comme un exercice pour le lecteur.

Résumé

Lors de l’utilisation de bases de données relationnelles, il est courant que les requêtes extrayent leurs données à partir de plusieurs tables associées. Les sous-requêtes et JOIN les requêtes corrélées fournissent deux techniques différentes pour accéder aux données à partir de tables associées dans une requête. Dans les tutoriels précédents, nous avons le plus souvent utilisé des sous-requêtes corrélées, car TableAdapter ne peut pas générer INSERTautomatiquement les instructions , UPDATEet DELETE pour les requêtes impliquant JOIN s. Bien que ces valeurs puissent être fournies manuellement, lors de l’utilisation d’instructions SQL ad hoc, toutes les personnalisations sont remplacées lorsque l’Assistant Configuration de TableAdapter est terminé.

Heureusement, les TableAdapters créés à l’aide de procédures stockées ne souffrent pas de la même fragilité que ceux créés à l’aide d’instructions SQL ad hoc. Par conséquent, il est possible de créer un TableAdapter dont la requête main utilise un lors de JOIN l’utilisation de procédures stockées. Dans ce tutoriel, nous avons vu comment créer un tel TableAdapter. Nous avons commencé par utiliser une JOINrequête -less SELECT pour la requête TableAdapter s main afin que les procédures stockées d’insertion, de mise à jour et de suppression correspondantes soient créées automatiquement. Une fois la configuration initiale de TableAdapter terminée, nous avons augmenté la SelectCommand procédure stockée pour utiliser un JOIN et ré-exécuté l’Assistant Configuration de TableAdapter pour mettre à jour les EmployeesDataTable colonnes s.

Ré-exécution de l’Assistant Configuration de TableAdapter a automatiquement mis à jour les EmployeesDataTable colonnes pour refléter les champs de données retournés par la Employees_Select procédure stockée. Nous aurions également pu ajouter ces colonnes manuellement au DataTable. Nous allons explorer l’ajout manuel de colonnes au DataTable dans le tutoriel suivant.

Bonne programmation !

À 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 comme consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Il est accessible à l’adressemitchell@4GuysFromRolla.com . ou via son blog, qui se trouve à l’adresse http://ScottOnWriting.NET.

Remerciements spéciaux à

Cette série de tutoriels a été examinée par de nombreux réviseurs utiles. Les principaux réviseurs de ce tutoriel étaient Hilton Geisenow, David Suru et Teresa Murphy. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.