Mise à jour du TableAdapter pour l’utilisation de jointures (C#)
par Scott Mitchell
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 JOIN
des. 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 , UPDATE
et 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 InsertCommand
propriétés , UpdateCommand
et 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 CategoryName
exemple).
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 , UPDATE
et DELETE
correspondantes INSERT
si 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
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 INSERT
automatiquement des instructions , UPDATE
et 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 INSERT
instructions , UPDATE
etDELETE
, car la requête main contient un JOIN
.
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 CategoryName
SupplierName
figure 3.
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 InsertCommand
propriétés , UpdateCommand
et DeleteCommand
. Pour confirmer cela, cliquez sur TableAdapter dans le Designer, puis accédez à la Fenêtre Propriétés. Vous verrez que les InsertCommand
propriétés , UpdateCommand
et DeleteCommand
sont définies sur (Aucun).
Figure 4 : Les InsertCommand
propriétés , UpdateCommand
et 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 InsertCommand
propriétés , UpdateCommand
et 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 INSERT
instructions , UPDATE
et 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 , UPDATE
et DELETE
générées INSERT
automatiquement 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 , UPDATE
et DELETE
générées INSERT
automatiquement par TableAdapter est, heureusement, limitée aux instructions SQL ad hoc. Si votre TableAdapter utilise des procédures stockées, vous pouvez personnaliser les SelectCommand
procédures stockées , InsertCommand
, UpdateCommand
ou 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 .
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 , UPDATE
et 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_Update
et Employees_Delete
, comme illustré dans la figure 6.
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.
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_Update
et 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 InsertCommand
propriétés , UpdateCommand
et DeleteCommand
sont correctement configurées pour appeler les procédures stockées correspondantes.
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 InsertCommand
propriétés , UpdateCommand
et 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).
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 lesInsertCommand
propriétés ,UpdateCommand
etDeleteCommand
, car leSelectCommand
contient maintenant unJOIN
. 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
.
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
.
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.cs
. 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
.
using System;
using System.Data;
using System.Configuration;
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 NorthwindWithSprocsTableAdapters;
[System.ComponentModel.DataObject]
public class EmployeesBLLWithSprocs
{
private EmployeesTableAdapter _employeesAdapter = null;
protected EmployeesTableAdapter Adapter
{
get
{
if (_employeesAdapter == null)
_employeesAdapter = new EmployeesTableAdapter();
return _employeesAdapter;
}
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, true)]
public NorthwindWithSprocs.EmployeesDataTable GetEmployees()
{
return Adapter.GetEmployees();
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Delete, true)]
public bool DeleteEmployee(int employeeID)
{
int rowsAffected = Adapter.Delete(employeeID);
// Return true if precisely one row was deleted, otherwise false
return rowsAffected == 1;
}
}
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.
Figure 12 : Configurer ObjectDataSource pour utiliser la EmployeesBLLWithSprocs
classe (cliquer pour afficher l’image en taille réelle)
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 Title
de , LastName
, FirstName
ManagerFirstName
, 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).
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.
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 laOrders
table avant de supprimer l’enregistrementEmployees
. 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 INSERT
automatiquement les instructions , UPDATE
et 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 JOIN
requê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.