Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
par Scott Mitchell
Lors de l’utilisation d’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 à partir 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 une jointure dans sa requête principale.
Présentation
Avec les bases de données relationnelles, les données qui nous intéressent sont souvent réparties entre plusieurs tables. Par exemple, lors de l’affichage des informations sur le produit, nous souhaitons probablement répertorier les noms de chaque catégorie et nom de fournisseur correspondants. La table Products
comporte des valeurs CategoryID
et SupplierID
, mais les noms réels des catégories et des fournisseurs se trouvent respectivement dans la table Categories
et la table Suppliers
.
Pour récupérer des informations d’une autre table associée, nous pouvons utiliser des sous-requêtes corrélées ou JOIN
s. Une sous-requête corrélée est une requête imbriquée SELECT
qui fait 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 principale pour retourner les noms de catégorie et de fournisseur pour chaque produit. A JOIN
est une construction SQL qui fusionne les lignes associées à partir de deux tables différentes. Nous avons utilisé une JOIN
dans le didacticiel Interroger des données avec le didacticiel SqlDataSource Control pour afficher des informations de catégorie en même temps que chaque produit.
La raison pour laquelle nous avons évité d'utiliser JOIN
s avec les TableAdapters est en raison des limitations de l'Assistant TableAdapter pour générer automatiquement les instructions correspondantes INSERT
, UPDATE
, et DELETE
. Plus précisément, si la requête principale de TableAdapter contient des JOIN
, TableAdapter ne peut pas créer automatiquement les instructions SQL ad hoc ou les procédures stockées pour ses propriétés InsertCommand
, UpdateCommand
, et DeleteCommand
.
Dans ce tutoriel, nous allons brièvement comparer et contraster les sous-requêtes corrélées et JOIN
avant d’explorer comment créer un TableAdapter qui inclut des JOIN
dans sa requête principale.
Comparaison et contraste des sous-requêtes etJOIN
des sous-requêtes corrélées
Rappelez-vous que le ProductsTableAdapter
créé dans le premier tutoriel le Northwind
DataSet utilise des sous-requêtes corrélées pour obtenir, pour chaque produit, sa catégorie et le nom du fournisseur correspondant. La ProductsTableAdapter
requête principale 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 (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID)
- sont des requêtes SELECT
qui retournent une valeur unique par produit en tant que colonne supplémentaire dans la liste de colonnes de l’instruction externe SELECT
.
Vous pouvez également utiliser une JOIN
option pour retourner 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
à 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
Une JOIN
fusion des enregistrements d’une table avec des enregistrements d’une autre table en fonction de certains critères. Dans la requête ci-dessus, par exemple, l’instruction LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID
est destinée à SQL Server pour fusionner chaque enregistrement de produit avec l’enregistrement de catégorie dans laquelle la valeur CategoryID
correspond à la valeur CategoryID
du produit. Le résultat fusionné nous permet d’utiliser les champs de catégorie correspondants pour chaque produit (par CategoryName
exemple).
Remarque
JOIN
sont couramment utilisés lors de l’interrogation de données à partir de bases de données relationnelles. Si vous débutez avec la syntaxe JOIN
ou si vous avez besoin de vous rafraîchir un peu la mémoire sur son utilisation, je recommande le didacticiel de jointure SQL sur W3 Schools. Vous pouvez également lire les JOIN
sections Principes fondamentaux et Principes de base de la sous-requête de la documentation en ligne de SQL.
Étant donné que les sous-requêtes JOIN
et les sous-requêtes corrélées peuvent être utilisées pour récupérer des données associées à partir d’autres tables, de nombreux développeurs se retrouvent à se gratter la tête et se demandent quelle approche utiliser. Tous les gourous SQL à qui j’ai parlé ont dit à peu près la même chose, que cela ne change pas vraiment les performances, car SQL Server produira des plans d'exécution presque identiques. Leur conseil, alors, est d’utiliser la technique que vous et votre équipe êtes le plus à l’aise avec. Il mérite de noter qu’après avoir transmis ces conseils, ces experts expriment immédiatement leur préférence de JOIN
s’exprimer sur les sous-requêtes corrélées.
Lors de la création d’une couche d’accès aux données à l’aide de Jeux de données 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 correspondantes INSERT
, UPDATE
et DELETE
si la requête principale contient des JOIN
, 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 Jeu de données typé temporaire dans le ~/App_Code/DAL
dossier. Pendant l’Assistant Configuration de TableAdapter, choisissez d’utiliser des instructions SQL ad hoc et saisissez la requête suivante SELECT
(voir 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 contenant JOIN
des éléments (cliquez pour afficher l’image de taille complète)
Par défaut, TableAdapter créera automatiquement les instructions pour INSERT
, UPDATE
et DELETE
basées sur la requête principale. Si vous cliquez sur le bouton Avancé, vous pouvez voir que cette fonctionnalité est activée. Malgré ce paramètre, le TableAdapter ne pourra pas créer les instructions INSERT
, UPDATE
, et DELETE
car la requête principale contient un JOIN
.
Figure 2 : Entrer une requête principale qui contient JOIN
s
Cliquez sur Terminer pour finaliser l'Assistant. À ce stade, votre Concepteur DataSet inclut un seul TableAdapter avec un DataTable contenant des colonnes correspondant à chacun des champs retournés dans la liste des colonnes de la requête SELECT
. Cela inclut le CategoryName
et le SupplierName
, comme le montre la figure 3.
Figure 3 : DataTable inclut une colonne pour chaque champ retourné dans la liste des colonnes
Bien que DataTable ait les colonnes appropriées, TableAdapter manque de valeurs pour ses propriétés InsertCommand
, UpdateCommand
, et DeleteCommand
. Pour confirmer cela, cliquez sur TableAdapter dans le Concepteur, puis accédez à la fenêtre Propriétés. Vous verrez que les propriétés InsertCommand
, UpdateCommand
et DeleteCommand
sont définies sur (Aucun).
Figure 4 : Les propriétés InsertCommand
, UpdateCommand
et DeleteCommand
sont définies sur (Aucun) (Cliquez pour afficher l’image de taille complète)
Pour contourner cette lacune, nous pouvons fournir manuellement les instructions et paramètres SQL pour les propriétés InsertCommand
, UpdateCommand
, et DeleteCommand
via la fenêtre Propriétés. Nous pourrions également commencer par configurer la requête principale du TableAdapter afin de ne pas inclure de JOIN
. Cela permettra aux instructions INSERT
, UPDATE
et DELETE
d'être générées automatiquement pour nous. Une fois l’Assistant terminé, nous pourrions ensuite mettre à jour manuellement les TableAdapters SelectCommand
à partir de la fenêtre Propriétés afin qu'ils incluent la syntaxe JOIN
.
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 principale de TableAdapter est reconfigurée via l’Assistant, les instructions INSERT
, UPDATE
, et DELETE
générées automatiquement sont recréées. Cela signifie que toutes les personnalisations que nous avons effectuées ultérieurement seraient perdues si nous avons cliqué avec le bouton droit sur TableAdapter, choisi Configurer à partir du menu contextuel et terminé à nouveau l’Assistant.
La fragilité des instructions générées INSERT
automatiquement par TableAdapter, UPDATE
et les DELETE
instructions sont, heureusement, limitées aux instructions SQL ad hoc. Si votre TableAdapter utilise des procédures stockées, vous pouvez personnaliser les procédures stockées SelectCommand
, InsertCommand
, UpdateCommand
ou DeleteCommand
et réexécuter l’Assistant Configuration de TableAdapter sans craindre que les procédures stockées ne soient modifiées.
Au cours des prochaines étapes, nous allons créer un TableAdapter qui, dans un premier temps, utilise une requête principale omettant les éléments 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 ce SelectCommand
afin qu'il utilise un JOIN
qui retourne des colonnes supplémentaires à partir de tables associées. Enfin, nous allons créer une classe de couche 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 didacticiel, nous allons ajouter un TableAdapter et un DataTable fortement typé pour la table Employees
dans le DataSet NorthwindWithSprocs
. La Employees
table contient un ReportsTo
champ qui spécifie le EmployeeID
du responsable de l'employé. Par exemple, l'employée Anne Dodsworth a une ReportTo
valeur de 5, qui est la EmployeeID
de Steven Buchanan. Par conséquent, Anne signale à Steven, son manager. En plus de signaler la valeur de ReportsTo
chaque employé, nous pourrions également récupérer le nom de son responsable. Cette opération peut être effectuée à l’aide d’un JOIN
. Toutefois, l’utilisation d’un élément JOIN
lors de la création initiale d’un 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 la requête principale ne contient pas de JOIN
. Ensuite, à l’étape 2, nous allons mettre à jour la procédure stockée principale de requête 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 Concepteur, sélectionnez l’option Ajouter dans le menu contextuel, puis sélectionnez l’élément de menu TableAdapter. Cette opération lance l’Assistant Configuration de TableAdapter. Comme le montre la figure 5, demandez à l’Assistant de créer de nouvelles procédures stockées, puis cliquez sur Suivant. Pour un rafraîchissement sur la création de nouvelles procédures stockées à partir de l'assistant TableAdapter, consultez le didacticiel Création de nouvelles procédures stockées pour les TableAdapters du DataSet typé.
Figure 5 : Sélectionnez l’option Créer de nouvelles procédures stockées (cliquez pour afficher l’image de taille complète)
Utilisez l’instruction suivante SELECT
pour la requête principale de TableAdapter :
SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees
Étant donné que cette requête n’inclut pas de JOIN
, l’Assistant TableAdapter crée automatiquement des procédures stockées avec des instructions correspondantes INSERT
, UPDATE
, et DELETE
, ainsi qu’une procédure stockée pour l’exécution de la requête principale.
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 : Nommer les procédures stockées de TableAdapter (cliquez pour afficher l’image de taille complète)
L’étape finale nous invite à nommer les méthodes de TableAdapter. Utilisez Fill
et GetEmployees
en tant que noms de méthode. Veillez également à ce que la case à cocher pour les méthodes Create (GenerateDBDirectMethods), qui envoient des mises à jour directement à la base de données, reste cochée.
Figure 7 : Nommer les méthodes Fill
de TableAdapter et GetEmployees
(Cliquez pour afficher l’image de taille complète)
Une fois l’Assistant terminé, prenez un moment pour examiner les procédures stockées dans la base de données. Vous devriez voir quatre nouvelles : Employees_Select
, , Employees_Insert
Employees_Update
, et Employees_Delete
. Ensuite, inspectez le EmployeesDataTable
et le EmployeesTableAdapter
qui viennent d'être créés. DataTable contient une colonne pour chaque champ retourné par la requête principale. Cliquez sur TableAdapter, puis accédez à la fenêtre Propriétés. Vous verrez que les propriétés InsertCommand
, UpdateCommand
et DeleteCommand
sont correctement configurées pour appeler les procédures stockées correspondantes.
Figure 8 : TableAdapter inclut les fonctionnalités d’insertion, de mise à jour et de suppression (cliquez pour afficher l’image de taille complète)
Lorsque les procédures stockées pour l'insertion, la mise à jour et la suppression sont créées automatiquement et que les propriétés InsertCommand
, UpdateCommand
, et DeleteCommand
sont correctement configurées, nous sommes prêts à personnaliser la procédure stockée SelectCommand
pour retourner des informations supplémentaires sur chaque responsable de l'employé. Plus précisément, nous devons mettre à jour la Employees_Select
procédure stockée pour utiliser un JOIN
et retourner les valeurs FirstName
et LastName
du gestionnaire. Une fois la procédure stockée mise à jour, nous devons mettre à jour le DataTable afin qu’il inclut ces colonnes supplémentaires. Nous aborderons ces deux tâches dans les étapes 2 et 3.
Étape 2 : Personnalisation de la procédure stockée pour inclure unJOIN
Commencez par accéder à l’Explorateur de serveurs, en explorant le dossier Procédures stockées de la base de données Northwind et en ouvrant 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 renvoyer le prénom et le 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 l’Explorateur de serveurs 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 la figure 9).
Figure 9 : Les résultats des procédures stockées sont affichés dans la fenêtre sortie (cliquez pour afficher l’image de taille complète)
Étape 3 : Mise à jour des colonnes de DataTable
À ce stade, la Employees_Select
procédure stockée retourne les valeurs ManagerFirstName
et ManagerLastName
, mais ces colonnes manquent dans le EmployeesDataTable
. Ces colonnes manquantes peuvent être ajoutées à DataTable de deux façons :
- Manuellement : cliquez avec le bouton droit sur dataTable dans le Concepteur DataSet 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. Lors de l’utilisation d’instructions SQL ad hoc, l’Assistant supprime également les propriétésInsertCommand
,UpdateCommand
, etDeleteCommand
puisque 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é manuellement l’ajout de colonnes DataTable dans les didacticiels précédents, notamment Master/Detail Using a Bulleted List of Master Records with a Details DataList and Uploading Files, et nous allons examiner ce processus plus en détail dans notre prochain tutoriel. Pour ce tutoriel, nous allons toutefois utiliser l’approche automatique via l’Assistant Configuration de TableAdapter.
Commencez par cliquer avec le bouton droit sur EmployeesTableAdapter
et sélectionnez Configurer dans le menu contextuel. Cela affiche l’Assistant Configuration de TableAdapter, qui répertorie les procédures stockées utilisées pour sélectionner, insérer, mettre à jour et supprimer, 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 maintenant les champs ManagerFirstName
et ManagerLastName
.
Figure 10 : L’Assistant affiche la liste de colonnes mise à jour de la Employees_Select
procédure stockée (cliquez pour afficher l’image de taille complète)
Terminez l’Assistant en cliquant sur Terminer. Après être retourné(e) au Concepteur DataSet, EmployeesDataTable
inclut deux colonnes supplémentaires : ManagerFirstName
et ManagerLastName
.
Figure 11 : Contient EmployeesDataTable
deux nouvelles colonnes (cliquez pour afficher l’image de taille complète)
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, nous allons créer une page web qui permet aux utilisateurs d’afficher et de supprimer des employés. Avant de créer une telle page, toutefois, 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 cette nouvelle méthode fournit moins de méthodes et utilise le NorthwindWithSprocs
DataSet (au lieu de 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é Adapter
de la classe retourne une instance de NorthwindWithSprocs
DataSet EmployeesTableAdapter
. Cela est utilisé par la classe GetEmployees
et les méthodes DeleteEmployee
. La méthode GetEmployees
appelle la méthode correspondante EmployeesTableAdapter
, qui invoque la procédure stockée GetEmployees
et où les résultats sont enregistrés dans un Employees_Select
. La méthode DeleteEmployee
appelle de même la méthode EmployeesTableAdapter
, qui invoque la procédure stockée Delete
.
Étape 5 : Utilisation des données dans la couche Présentation
Une fois la EmployeesBLLWithSprocs
classe terminée, nous sommes prêts à travailler avec les données des employés via une page ASP.NET. Ouvrez la page JOINs.aspx
dans le dossier AdvancedDAL
et faites glisser un GridView à partir de la boîte à outils vers le Concepteur, en définissant sa propriété ID
sur Employees
. Ensuite, à partir de la balise active gridView, liez la grille à un nouveau contrôle ObjectDataSource nommé EmployeesDataSource
.
Configurez l'ObjectDataSource pour utiliser la classe EmployeesBLLWithSprocs
et, à partir des onglets SELECT et DELETE, assurez-vous que les méthodes GetEmployees
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 classe (EmployeesBLLWithSprocs
de taille complète)
Figure 13 : Faire Utiliser ObjectDataSource avec les méthodes GetEmployees
et DeleteEmployee
(Cliquez pour afficher l’image en taille réelle)
Visual Studio ajoute un Objet BoundField à GridView pour chacune des EmployeesDataTable
colonnes. Supprimez tous ces BoundFields à l’exception de Title
, LastName
, FirstName
, ManagerFirstName
, et ManagerLastName
, et renommez les propriétés HeaderText
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 à partir de sa balise active. Ensuite, modifiez la propriété ObjectDataSource de la valeur définie par l’Assistant ObjectDataSource (OldValuesParameterFormatString
) à sa valeur par défaut (original_{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’ils en ont un).
Figure 14 : La JOIN
Employees_Select
procédure stockée renvoie le nom du gestionnaire (cliquez pour afficher l’image de taille complète)
Cliquez sur le bouton Supprimer pour démarrer le flux de travail de suppression, ce qui aboutit à l’exécution de la Employees_Delete
procédure stockée. Toutefois, l’instruction tentée DELETE
dans la procédure stockée échoue en raison d’une violation de contrainte de clé étrangère (voir la 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é disposant de commandes correspondantes entraîne une violation de contrainte de clé étrangère (cliquez pour afficher l’image de taille complète)
Pour permettre à un employé d’être supprimé, vous pouvez :
- Mettez à jour la contrainte de clé étrangère pour effectuer un effacement 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 didacticiel Utilisation de procédures stockées existantes pour les TableAdapters des Typed DataSets.
Je laisse ça comme un exercice pour le lecteur.
Résumé
Lorsque vous utilisez des 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 corrélées et JOIN
s fournissent deux techniques différentes pour accéder aux données à partir de tables associées dans une requête. Dans les didacticiels précédents, nous avons généralement utilisé des sous-requêtes corrélées, car TableAdapter ne peut pas générer automatiquement les instructions INSERT
, UPDATE
, et DELETE
pour les requêtes impliquant des JOIN
s. Bien que ces valeurs puissent être fournies manuellement, lorsque vous utilisez des instructions SQL ad hoc, toutes les personnalisations seront remplacées une fois que l'Assistant de Configuration de TableAdapter aura été terminé.
Heureusement, Les TableAdapters créés à l’aide de procédures stockées ne souffrent pas de la même fragilité que celles créées à l’aide d’instructions SQL ad hoc. Par conséquent, il est possible de créer un TableAdapter dont la requête principale utilise une JOIN
lors de l’utilisation de procédures stockées. Dans ce tutoriel, nous avons vu comment créer un tel TableAdapter. Nous avons commencé à utiliser une requête sans JOIN
pour la requête principale du TableAdapter, afin que les procédures d'insertion, de mise à jour et de suppression correspondantes soient automatiquement créées SELECT
. Une fois la configuration initiale de TableAdapter terminée, nous avons modifié la SelectCommand
procédure stockée pour utiliser un JOIN
et réexécuté l'assistant de configuration de TableAdapter pour mettre à jour les colonnes de EmployeesDataTable
.
En réexécutant l’Assistant de Configuration TableAdapter, les colonnes EmployeesDataTable
ont été automatiquement mises à jour pour refléter les champs de données retournés par la procédure stockée Employees_Select
. Sinon, nous pourrions avoir ajouté ces colonnes manuellement à DataTable. Nous allons explorer manuellement l’ajout 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 en tant que consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 en 24 heures. On peut le joindre à mitchell@4GuysFromRolla.com.
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 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.