Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
von Scott Mitchell
Beim Arbeiten mit einer Datenbank ist es üblich, Daten anzufordern, die über mehrere Tabellen verteilt sind. Zum Abrufen von Daten aus zwei verschiedenen Tabellen können wir entweder eine korrelierte Unterabfrage oder einen JOIN-Vorgang verwenden. In diesem Lernprogramm vergleichen wir korrelierte Unterabfragen und die JOIN-Syntax, bevor Sie sich ansehen, wie Sie einen TableAdapter erstellen, der eine JOIN in der Hauptabfrage enthält.
Einleitung
Bei relationalen Datenbanken sind die Daten, mit denen wir arbeiten möchten, häufig auf mehrere Tabellen verteilt. Wenn beispielsweise Produktinformationen angezeigt werden, möchten wir wahrscheinlich die entsprechenden Produktkategorien und Lieferantennamen auflisten. Die Products
Tabelle enthält CategoryID
und SupplierID
Werte, aber die tatsächlichen Kategorie- und Lieferantennamen sind jeweils in den Tabellen Categories
und Suppliers
enthalten.
Um Informationen aus einer anderen verknüpften Tabelle abzurufen, können wir entweder korrelierte Unterabfragen oder JOIN
s verwenden. Eine korrelierte Unterabfrage ist eine geschachtelte SELECT
Abfrage, die auf Spalten in der äußeren Abfrage verweist. Im Lernprogramm zum Erstellen einer Datenzugriffsebene haben wir beispielsweise zwei korrelierte Unterabfragen in der ProductsTableAdapter
Hauptabfrage verwendet, um die Kategorie- und Lieferantennamen für jedes Produkt zurückzugeben. A JOIN
ist ein SQL-Konstrukt, das verwandte Zeilen aus zwei verschiedenen Tabellen zusammenführt. Wir haben eine JOIN
im Lernprogramm zum Abfragen von Daten mit dem SqlDataSource-Steuerelement verwendet, um Kategorieinformationen zusammen mit den einzelnen Produkten anzuzeigen.
Der Grund, warum wir auf die Verwendung von JOIN
mit den TableAdapters verzichtet haben, sind die Einschränkungen des TableAdapter-Assistenten bei der automatischen Generierung entsprechender INSERT
, UPDATE
und DELETE
Anweisungen. Wenn die Hauptabfrage des TableAdapters JOIN
s enthält, kann der TableAdapter die Ad-hoc-SQL-Anweisungen oder gespeicherten Prozeduren für die zugehörigen InsertCommand
, UpdateCommand
und DeleteCommand
-Eigenschaften nicht automatisch erstellen.
In diesem Lernprogramm werden wir kurz korrelierte Unterabfragen und JOIN
s vergleichen und gegenüberstellen, bevor wir erkunden, wie ein TableAdapter erstellt wird, der JOIN
s in seiner Hauptabfrage enthält.
Vergleichen und Kontrastieren korrelierter Unterabfragen undJOIN
-n
Erinnern Sie sich daran, dass das im ersten Lernprogramm im ProductsTableAdapter
DataSet erstellte Northwind
korrelierte Unterabfragen verwendet, um die entsprechende Kategorie und den Lieferantennamen jedes Produkts abzurufen. Die ProductsTableAdapter
Hauptabfrage wird unten angezeigt.
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
Die beiden korrelierten Unterabfragen - (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID)
und (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID)
- sind SELECT
-Abfragen, die für jedes Produkt einen einzelnen Wert als zusätzliche Spalte in der Spaltenliste der äußeren SELECT
-Anweisung zurückgeben.
Alternativ kann ein JOIN
verwendet werden, um den Lieferanten und den Kategorienamen jedes Produkts zurückzugeben. Die folgende Abfrage gibt die gleiche Ausgabe wie die oben genannte abfrage zurück, verwendet JOIN
jedoch anstelle von Unterabfragen:
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
Ein JOIN
führt Datensätze aus einer Tabelle mit Datensätzen aus einer anderen Tabelle basierend auf bestimmten Kriterien zusammen. In der obigen Abfrage z. B. wird SQL Server angewiesen, jeden Produktdatensatz mit dem Kategoriedatensatz zusammenzuführen, LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID
dessen CategoryID
Wert dem Wert des CategoryID
Produkts entspricht. Das zusammengeführte Ergebnis ermöglicht es uns, mit den entsprechenden Kategoriefeldern für jedes Produkt zu arbeiten (wie z. B. CategoryName
).
Hinweis
JOIN
s werden häufig beim Abfragen von Daten aus relationalen Datenbanken verwendet. Wenn Sie neu in der JOIN
Syntax sind oder Ihre Kenntnisse auffrischen müssen, würde ich das SQL Join-Lernprogramm bei W3 Schools empfehlen. Lesenswert sind auch die JOIN
Abschnitte "Grundlagen " und " Subquery Fundamentals " der SQL-Bücher Online.
Da JOIN
s und korrelierte Unterabfragen zum Abrufen verwandter Daten aus anderen Tabellen verwendet werden können, müssen viele Entwickler ihre Köpfe kratzen und sich fragen, welcher Ansatz verwendet werden soll. Alle SQL-Gurus, mit denen ich gesprochen habe, haben ungefähr dasselbe gesagt, dass es nicht wirklich wichtig ist, leistungsmäßig, da SQL Server ungefähr identische Ausführungspläne produzieren wird. Ihre Ratschläge sind dann die Verwendung der Technik, mit der Sie und Ihr Team am besten vertraut sind. Es ist zu beachten, dass diese Experten, nachdem sie diesen Rat gegeben haben, sofort ihre Vorlieben JOIN
gegenüber korrelierten Unterabfragen ausdrücken.
Beim Erstellen einer Datenzugriffsebene mit typierten DataSets funktionieren die Tools besser bei der Verwendung von Unterabfragen. Insbesondere generiert der TableAdapter-Assistent keine entsprechenden INSERT
, UPDATE
, und DELETE
-Anweisungen automatisch, wenn die Hauptabfrage JOIN
-s enthält, generiert diese Anweisungen jedoch automatisch, wenn korrelierte Unterabfragen verwendet werden.
Um diesen Mangel zu untersuchen, erstellen Sie ein temporäres Typed DataSet im Ordner ~/App_Code/DAL
. Wählen Sie während des TableAdapter-Konfigurations-Assistenten die Verwendung von AD-hoc-SQL-Anweisungen aus, und geben Sie die folgende SELECT
Abfrage ein (siehe Abbildung 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
Abbildung 1: Eingeben einer Hauptabfrage, die 's' enthält JOIN
(Klicken Sie, um das Bild in voller Größe anzuzeigen)
Standardmäßig erstellt der TableAdapter automatisch INSERT
, UPDATE
und DELETE
Anweisungen basierend auf der Hauptabfrage. Wenn Sie auf die Schaltfläche "Erweitert" klicken, können Sie sehen, dass dieses Feature aktiviert ist. Trotz dieser Einstellung kann der TableAdapter die INSERT
, UPDATE
und DELETE
Anweisungen nicht erstellen, da die Hauptabfrage eine JOIN
enthält.
Abbildung 2: Eingeben einer Hauptabfrage, die s enthält JOIN
Klicken Sie auf Fertig stellen, um den Assistenten abzuschließen. An diesem Punkt enthält der DataSet-Designer einen einzelnen TableAdapter mit einer DataTable, die Spalten für jedes der Felder umfasst, die in der Spaltenliste der Abfrage SELECT
zurückgegeben werden. Dies schließt die CategoryName
und SupplierName
, wie Abbildung 3 zeigt, ein.
Abbildung 3: Die DataTable enthält eine Spalte für jedes Feld, das in der Spaltenliste zurückgegeben wird.
Während die DataTable über die entsprechenden Spalten verfügt, fehlen dem TableAdapter die Werte für seine InsertCommand
, UpdateCommand
und DeleteCommand
Eigenschaften. Um dies zu bestätigen, klicken Sie im Designer auf den TableAdapter, und wechseln Sie dann zum Eigenschaftenfenster. Dort sehen Sie, dass die InsertCommand
, UpdateCommand
und DeleteCommand
Eigenschaften, auf (Keine) festgelegt sind.
Abbildung 4: Die InsertCommand
Und UpdateCommand
DeleteCommand
Eigenschaften sind auf (Keine) festgelegt (Klicken, um das Bild in voller Größe anzuzeigen)
Um dieses Manko zu umgehen, können wir die SQL-Anweisungen und Parameter für die Eigenschaften InsertCommand
, UpdateCommand
und DeleteCommand
über das Eigenschaftenfenster manuell bereitstellen. Alternativ können wir mit der Konfiguration der TableAdapter-Hauptabfrage beginnen, um keineJOIN
s einzuschließen. Dadurch können die INSERT
, UPDATE
und DELETE
Anweisungen automatisch generiert werden. Nach Abschluss des Assistenten konnten wir den TableAdapter SelectCommand
dann manuell aus dem Eigenschaftenfenster aktualisieren, sodass er die JOIN
Syntax enthält.
Während dieser Ansatz funktioniert, ist er sehr anfällig, wenn Ad-hoc-SQL-Abfragen verwendet werden, da jedes Mal, wenn die Hauptabfrage des TableAdapters über den Assistenten neu konfiguriert wird, die automatisch generierten INSERT
, UPDATE
, und DELETE
Anweisungen neu erstellt werden. Dies bedeutet, dass alle später vorgenommenen Anpassungen verloren gehen würden, wenn wir mit der rechten Maustaste auf das TableAdapter-Objekt geklickt haben, im Kontextmenü "Konfigurieren" ausgewählt und den Assistenten erneut abgeschlossen haben.
Die Sprödigkeit der automatisch generierten INSERT
, UPDATE
, und DELETE
-Anweisungen des TableAdapters ist glücklicherweise auf Ad-hoc-SQL-Anweisungen beschränkt. Wenn Ihr TableAdapter gespeicherte Prozeduren verwendet, können Sie die gespeicherten Prozeduren SelectCommand
, InsertCommand
, UpdateCommand
oder DeleteCommand
anpassen und den Assistenten für die TableAdapter-Konfiguration erneut ausführen, ohne befürchten zu müssen, dass die gespeicherten Prozeduren geändert werden.
Über die nächsten Schritte werden wir einen TableAdapter erstellen, der zunächst eine Hauptabfrage verwendet, die alle JOIN
-Elemente auslässt, sodass die entsprechenden gespeicherten Prozeduren zum Einfügen, Aktualisieren und Löschen automatisch generiert werden. Anschließend aktualisieren wir das SelectCommand
, damit ein JOIN
verwendet wird, das zusätzliche Spalten aus verknüpften Tabellen zurückgibt. Schließlich erstellen wir eine entsprechende Business Logic Layer-Klasse und veranschaulichen die Verwendung des TableAdapter in einer ASP.NET Webseite.
Schritt 1: Erstellen des TableAdapters mithilfe einer vereinfachten Hauptabfrage
In diesem Tutorial fügen wir eine TableAdapter und eine stark typisierte DataTable für die Employees
-Tabelle im NorthwindWithSprocs
-DataSet hinzu. Die Employees
Tabelle enthält ein ReportsTo
Feld, das den EmployeeID
Vorgesetzten des Mitarbeiters angegeben hat. Beispielsweise hat die Mitarbeiterin Anne Dodsworth den ReportTo
Wert 5, welcher identisch mit dem EmployeeID
von Steven Buchanan ist. Folglich berichtet Anne an Steven, ihren Vorgesetzten. Zusammen mit der Berichterstattung über den Wert jedes Mitarbeiters ReportsTo
möchten wir möglicherweise auch den Namen deren Vorgesetzten abrufen. Dies kann mithilfe einer JOIN
. Die Verwendung einer JOIN
beim Erstellen des TableAdapters verhindert jedoch, dass der Assistent automatisch die entsprechenden Einfüge-, Update- und Löschmöglichkeiten generiert. Daher erstellen wir zunächst einen TableAdapter, dessen Hauptabfrage keine JOIN
enthält. Dann aktualisieren wir in Schritt 2 die gespeicherte Prozedur der Hauptabfrage, um den Namen des Vorgesetzten über eine JOIN
abzurufen.
Öffnen Sie zunächst das NorthwindWithSprocs
DataSet im ~/App_Code/DAL
Ordner. Klicken Sie mit der rechten Maustaste auf den Designer, wählen Sie die Option "Hinzufügen" aus dem Kontextmenü aus, und wählen Sie das Menüelement "TableAdapter" aus. Dadurch wird der Konfigurations-Assistent "TableAdapter" gestartet. Wie in Abbildung 5 dargestellt, lassen Sie den Assistenten neue gespeicherte Prozeduren erstellen und klicken Sie auf "Weiter". Zur Auffrischung, wie man neue gespeicherte Prozeduren mit dem TableAdapter-Assistenten erstellt, konsultieren Sie das Tutorial Erstellen neuer gespeicherter Prozeduren für die TableAdapters des Typed DataSets.
Abbildung 5: Auswählen der Option "Neue gespeicherte Prozeduren erstellen" (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Verwenden Sie die folgende SELECT
Anweisung für die TableAdapter-Hauptabfrage:
SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees
Da diese Abfrage keine JOIN
-Elemente enthält, erstellt der TableAdapter-Assistent automatisch gespeicherte Prozeduren mit entsprechenden INSERT
, UPDATE
, und DELETE
-Anweisungen sowie eine gespeicherte Prozedur zum Ausführen der Hauptabfrage.
Im folgenden Schritt können wir die gespeicherten Prozeduren von TableAdapter benennen. Verwenden Sie die Namen Employees_Select
, Employees_Insert
, Employees_Update
und Employees_Delete
, wie in Abbildung 6 dargestellt.
Abbildung 6: Benennen der gespeicherten Prozeduren von TableAdapter (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Im letzten Schritt werden wir aufgefordert, die TableAdapter-Methoden zu benennen. Verwenden Fill
Und GetEmployees
als Methodennamen. Achten Sie außerdem darauf, dass die Methoden "Erstellen" aktiviert bleiben, um Aktualisierungen direkt an die Datenbank (GenerateDBDirectMethods) zu senden.
Abbildung 7: Benennen der TableAdapter-Methoden Fill
und GetEmployees
(Klicken Sie, um das Bild in voller Größe anzuzeigen)
Nach Abschluss des Assistenten nehmen Sie sich einen Moment Zeit, um die gespeicherten Prozeduren in der Datenbank zu überprüfen. Sie sollten vier neue sehen: Employees_Select
, , Employees_Insert
, Employees_Update
und Employees_Delete
. Überprüfen Sie als Nächstes die soeben erstellten EmployeesDataTable
und EmployeesTableAdapter
. Die DataTable enthält eine Spalte für jedes Feld, das von der Hauptabfrage zurückgegeben wird. Klicken Sie auf "TableAdapter", und wechseln Sie dann zum Fenster "Eigenschaften". Dort sehen Sie, dass die InsertCommand
Eigenschaften UpdateCommand
und Eigenschaften DeleteCommand
ordnungsgemäß konfiguriert sind, um die entsprechenden gespeicherten Prozeduren aufzurufen.
Abbildung 8: Das TableAdapter-Element enthält Die Funktionen "Einfügen", "Aktualisieren" und "Löschen" (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Mit den automatisch erstellten gespeicherten Prozeduren zum Einfügen, Aktualisieren und Löschen sowie der InsertCommand
, UpdateCommand
, DeleteCommand
ordnungsgemäß konfigurierten Eigenschaften können wir die gespeicherte Prozedur SelectCommand
anpassen, um zusätzliche Informationen über den Vorgesetzten jedes Mitarbeiters zurückzugeben. Insbesondere müssen wir die Employees_Select
gespeicherte Prozedur aktualisieren, um einen JOIN
zu verwenden und die Werte FirstName
und LastName
des Managers zurückzugeben. Nachdem die gespeicherte Prozedur aktualisiert wurde, müssen wir die DataTable aktualisieren, damit sie diese zusätzlichen Spalten enthält. Diese beiden Aufgaben werden in schritt 2 und 3 behandelt.
Schritt 2: Anpassen der gespeicherten Prozedur zum Einschließen einerJOIN
Beginnen Sie, indem Sie zum Server-Explorer wechseln, einen Drilldown in den Ordner "Gespeicherte Prozeduren der Northwind-Datenbank" ausführen und die Employees_Select
gespeicherte Prozedur öffnen. Wenn diese gespeicherte Prozedur nicht angezeigt wird, klicken Sie mit der rechten Maustaste auf den Ordner "Gespeicherte Prozeduren", und wählen Sie "Aktualisieren" aus. Aktualisieren Sie die gespeicherte Prozedur, sodass ein LEFT JOIN
den Vor- und Nachnamen des Managers zurückgibt.
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
Nachdem Sie die SELECT
Anweisung aktualisiert haben, speichern Sie die Änderungen, indem Sie zum Menü "Datei" wechseln und "Speichern" Employees_Select
auswählen. Alternativ können Sie auf das Symbol "Speichern" auf der Symbolleiste klicken oder STRG+S drücken. Klicken Sie nach dem Speichern der Änderungen mit der rechten Maustaste auf die Employees_Select
gespeicherte Prozedur im Server-Explorer, und wählen Sie "Ausführen" aus. Dadurch wird die gespeicherte Prozedur ausgeführt und die Ergebnisse im Ausgabefenster angezeigt (siehe Abbildung 9).
Abbildung 9: Die Ergebnisse gespeicherter Prozeduren werden im Ausgabefenster angezeigt (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Schritt 3: Aktualisieren der Datentabellenspalten
Zu diesem Zeitpunkt gibt die gespeicherte Prozedur Employees_Select
und ManagerFirstName
Werte zurück, aber der ManagerLastName
fehlen diese Spalten. Diese fehlenden Spalten können der DataTable auf zwei Arten hinzugefügt werden:
- Manuell – klicken Sie mit der rechten Maustaste auf die DataTable im DataSet-Designer, und wählen Sie im Menü "Hinzufügen" die Option "Spalte" aus. Anschließend können Sie die Spalte benennen und deren Eigenschaften entsprechend festlegen.
-
Automatisch – der TableAdapter-Konfigurations-Assistent aktualisiert die Datentabellenspalten so, dass sie die von der
SelectCommand
gespeicherten Prozedur zurückgegebenen Felder widerspiegeln. Wenn Sie Ad-hoc-SQL-Anweisungen verwenden, entfernt der Assistent auch dieInsertCommand
,UpdateCommand
undDeleteCommand
Eigenschaften, daSelectCommand
jetztJOIN
enthält. Wenn Sie gespeicherte Prozeduren verwenden, bleiben diese Befehlseigenschaften jedoch erhalten.
Wir haben das manuelle Hinzufügen von DataTable-Spalten in früheren Tutorials untersucht, einschließlich Master/Detail mit einer Aufzählungsliste von Master-Datensätzen mit einer Detail-DataList und Dateien hochladen, und wir werden diesen Prozess in unserem nächsten Tutorial erneut ausführlicher betrachten. In diesem Tutorial verwenden wir jedoch den automatischen Ansatz über den TableAdapter-Konfigurationsassistenten.
Klicken Sie zunächst mit der rechten Maustaste auf das EmployeesTableAdapter
Kontextmenü, und wählen Sie "Konfigurieren" aus. Dadurch wird der TableAdapter-Konfigurations-Assistent angezeigt, der die gespeicherten Prozeduren auflistet, die zum Auswählen, Einfügen, Aktualisieren und Löschen sowie deren Rückgabewerte und Parameter (falls vorhanden) verwendet werden. Abbildung 10 zeigt diesen Assistenten. Hier sehen wir, dass die gespeicherte Prozedur Employees_Select
jetzt die Felder ManagerFirstName
und ManagerLastName
zurückgibt.
Abbildung 10: Der Assistent zeigt die aktualisierte Spaltenliste für die Employees_Select
gespeicherte Prozedur an (Klicken, um das Bild in voller Größe anzuzeigen)
Schließen Sie den Assistenten ab, indem Sie auf "Fertig stellen" klicken. Wenn Sie zum DataSet-Designer zurückkehren, enthält dies EmployeesDataTable
zwei zusätzliche Spalten: ManagerFirstName
und ManagerLastName
.
Abbildung 11: Enthält EmployeesDataTable
zwei neue Spalten (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Um zu veranschaulichen, dass die aktualisierte Employees_Select
gespeicherte Prozedur wirksam ist und dass die Einfüge-, Aktualisierungs- und Löschfunktionen des TableAdapter-Elements weiterhin funktionsfähig sind, erstellen wir eine Webseite, auf der Benutzer Mitarbeiter anzeigen und löschen können. Bevor wir eine solche Seite erstellen, müssen wir jedoch zuerst eine neue Klasse in der Business Logic Layer erstellen, um mit Mitarbeitern aus dem NorthwindWithSprocs
DataSet zu arbeiten. In Schritt 4 erstellen wir eine EmployeesBLLWithSprocs
Klasse. In Schritt 5 verwenden wir diese Klasse von einer ASP.NET Seite.
Schritt 4: Implementieren der Geschäftslogikebene
Erstellen Sie eine neue Klassendatei im Ordner mit dem ~/App_Code/BLL
Namen EmployeesBLLWithSprocs.cs
. Diese Klasse imitiert die Semantik der vorhandenen EmployeesBLL
Klasse, nur diese neue Klasse bietet weniger Methoden und verwendet dataSet NorthwindWithSprocs
(anstelle des Northwind
DataSet). Fügen Sie der klasse EmployeesBLLWithSprocs
den folgenden Code hinzu.
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;
}
}
Die EmployeesBLLWithSprocs
Klasse s-Eigenschaft Adapter
gibt eine Instanz der NorthwindWithSprocs
DataSet s EmployeesTableAdapter
zurück. Dies wird von der Klasse s GetEmployees
und den Methoden DeleteEmployee
verwendet. Die GetEmployees
Methode ruft die entsprechende EmployeesTableAdapter
GetEmployees
Methode auf, die die gespeicherte Employees_Select
Prozedur aufruft und die Ergebnisse in einer EmployeeDataTable
ausgibt. Die DeleteEmployee
Methode ruft auf ähnliche Weise die EmployeesTableAdapter
s-Methode Delete
auf, die die Employees_Delete
gespeicherte Prozedur aufruft.
Schritt 5: Arbeiten mit den Daten in der Präsentationsebene
Nachdem der EmployeesBLLWithSprocs
Kurs abgeschlossen ist, können wir über eine ASP.NET Seite mit Mitarbeiterdaten zusammenarbeiten. Öffnen Sie die JOINs.aspx
-Seite im AdvancedDAL
-Ordner; ziehen Sie ein GridView aus der Toolbox auf den Designer und legen Sie dessen ID
-Eigenschaft auf Employees
fest. Binden Sie als Nächstes aus dem Smarttag von GridView das Raster an ein neues ObjectDataSource-Steuerelement mit dem Namen EmployeesDataSource
.
Konfigurieren Sie die ObjectDataSource so, dass sie die EmployeesBLLWithSprocs
Klasse verwendet. Stellen Sie sicher, dass die GetEmployees
und DeleteEmployee
Methoden in den Dropdownlisten der Registerkarten SELECT und DELETE ausgewählt werden. Klicken Sie auf "Fertig stellen", um die ObjectDataSource-Konfiguration abzuschließen.
Abbildung 12: Konfigurieren der ObjectDataSource für die Verwendung der EmployeesBLLWithSprocs
Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 13: Verwenden der ObjectDataSource-Methode (GetEmployees
DeleteEmployee
Klicken Sie, um das Bild in voller Größe anzuzeigen)
Visual Studio fügt der GridView für jede der EmployeesDataTable
Spalten ein BoundField hinzu. Entfernen Sie alle diese BoundFields mit Ausnahme von Title
, LastName
, FirstName
, ManagerFirstName
und ManagerLastName
und benennen Sie die HeaderText
-Eigenschaften der letzten vier BoundFields in Nachname, Vorname, Vorname des Vorgesetzten und Nachname des Vorgesetzten um.
Damit Benutzer Mitarbeiter von dieser Seite löschen können, müssen wir zwei Dinge ausführen. Weisen Sie zunächst die GridView an, Löschfunktionen bereitzustellen, indem Sie die Option "Löschen aktivieren" aus ihrem Smarttag überprüfen. Ändern Sie zweitens die ObjectDataSource-Eigenschaft OldValuesParameterFormatString
von dem vom ObjectDataSource-Assistenten (original_{0}
) festgelegten Wert in den Standardwert ({0}
). Nachdem Sie diese Änderungen vorgenommen haben, sollte ihr deklaratives GridView- und ObjectDataSource-Markup ähnlich wie folgt aussehen:
<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>
Testen Sie die Seite, indem Sie sie über einen Browser besuchen. Wie in Abbildung 14 dargestellt, listet die Seite jeden Mitarbeiter und seinen Vorgesetztennamen auf (vorausgesetzt, sie haben einen).
Abbildung 14: Die JOIN
in der Employees_Select
gespeicherten Prozedur gibt den Namen des Managers zurück (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Durch Klicken auf die Schaltfläche "Löschen" wird der Löschworkflow gestartet, der zur Ausführung der Employees_Delete
gespeicherten Prozedur führt. Die versuchte Anweisung in der gespeicherten DELETE
Prozedur schlägt jedoch aufgrund einer Verletzung der Fremdschlüsseleinschränkung fehl (siehe Abbildung 15). Insbesondere verfügt jeder Mitarbeiter über einen oder mehrere Datensätze in der Orders
Tabelle, wodurch der Löschvorgang fehlschlägt.
Abbildung 15: Wenn ein Mitarbeiter gelöscht wird, der mit entsprechenden Bestellungen verknüpft ist, führt dies zu einer Verletzung der Fremdschlüsseleinschränkung (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Damit ein Mitarbeiter gelöscht werden kann, können Sie folgende Aktionen ausführen:
- Aktualisieren Sie die Fremdschlüsseleinschränkung, um Löschvorgänge zu übernehmen.
- Löschen Sie die Datensätze manuell aus der
Orders
Tabelle für die Mitarbeiter, die Sie löschen möchten, oder - Aktualisieren Sie die
Employees_Delete
gespeicherte Prozedur, um zuerst die zugehörigen Datensätze aus derOrders
Tabelle zu löschen, bevor Sie denEmployees
Datensatz löschen. Wir haben diese Technik im Tutorial "Verwendung bestehender gespeicherter Prozeduren für TableAdapters in typisierten DataSets" diskutiert.
Ich lasse dies als Übung für den Leser.
Zusammenfassung
Beim Arbeiten mit relationalen Datenbanken ist es üblich, dass Abfragen ihre Daten aus mehreren verknüpften Tabellen abrufen. Korrelierte Unterabfragen und JOIN
-abfragen bieten zwei verschiedene Techniken für den Zugriff auf Daten aus verknüpften Tabellen in einer Abfrage. In früheren Lernprogrammen haben wir am häufigsten korrelierte Unterabfragen verwendet, da der TableAdapter keine INSERT
-, UPDATE
- und DELETE
-Anweisungen für Abfragen, die JOIN
betreffen, automatisch generieren kann. Während diese Werte manuell eingegeben werden können, werden bei Verwendung von Ad-hoc-SQL-Anweisungen alle Anpassungen überschrieben, wenn der TableAdapter-Konfigurationsassistent abgeschlossen ist.
Glücklicherweise leiden TableAdapters, die mit gespeicherten Prozeduren erstellt wurden, nicht unter der gleichen Sprödigkeit wie diejenigen, die mit Ad-hoc-SQL-Anweisungen erstellt wurden. Daher ist es möglich, ein TableAdapter-Objekt zu erstellen, dessen Hauptabfrage ein JOIN
bei Verwendung von gespeicherten Prozeduren benutzt. In diesem Tutorial sahen wir, wie so ein TableAdapter erstellt wird. Wir haben mit der Verwendung einer JOIN
-less-Abfrage SELECT
für die TableAdapter-Hauptabfrage begonnen, damit die entsprechenden gespeicherten Prozeduren zum Einfügen, Aktualisieren und Löschen automatisch erstellt werden. Nachdem die anfängliche Konfiguration des TableAdapter abgeschlossen war, haben wir die gespeicherte Prozedur SelectCommand
erweitert, um ein JOIN
zu nutzen, und den TableAdapter-Konfigurations-Assistenten erneut ausgeführt, um die Spalten von EmployeesDataTable
zu aktualisieren.
Beim erneuten Ausführen des TableAdapter-Konfigurations-Assistenten wurden die EmployeesDataTable
Spalten automatisch aktualisiert, um die von der Employees_Select
gespeicherten Prozedur zurückgegebenen Datenfelder wiederzugeben. Alternativ könnten wir diese Spalten manuell zur DataTable hinzugefügt haben. Im nächsten Lernprogramm werden wir das manuelle Hinzufügen von Spalten zur DataTable untersuchen.
Glückliche Programmierung!
Zum Autor
Scott Mitchell, Autor von sieben ASP/ASP.NET Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann bei mitchell@4GuysFromRolla.comerreicht werden.
Besonderer Dank an
Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Leitende Prüfer für dieses Lernprogramm waren Hilton Geisenow, David Suru und Teresa Murphy. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.