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
In früheren Lernprogrammen haben wir SQL-Anweisungen in unserem Code erstellt und die Anweisungen an die Datenbank übergeben, die ausgeführt werden sollen. Ein alternativer Ansatz besteht darin, gespeicherte Prozeduren zu verwenden, bei denen die SQL-Anweisungen in der Datenbank vordefiniert sind. In diesem Lernprogramm erfahren Sie, wie Sie mit dem TableAdapter-Assistenten neue gespeicherte Prozeduren für uns generieren können.
Einleitung
Die Datenzugriffsebene (Data Access Layer, DAL) für diese Lernprogramme verwendet Typed DataSets. Wie im Creating a Data Access Layer Tutorial erläutert, bestehen typisierte DataSets aus stark typisierten DataTables und TableAdapters. Die DataTables stellen die logischen Entitäten im System dar, während die TableAdapters mit der zugrunde liegenden Datenbank interagieren, um den Datenzugriff durchzuführen. Dazu gehört das Auffüllen der DataTables mit Daten, das Ausführen von Abfragen, die skalare Daten zurückgeben, und das Einfügen, Aktualisieren und Löschen von Datensätzen aus der Datenbank.
Die SQL-Befehle, die von den TableAdapters ausgeführt werden, können entweder ad-hoc-SQL-Anweisungen wie z. B. SELECT columnList FROM TableName
oder gespeicherte Prozeduren sein. Die TableAdapters in unserer Architektur verwenden ad-hoc SQL-Anweisungen. Viele Entwickler und Datenbankadministratoren bevorzugen jedoch gespeicherte Prozeduren gegenüber Ad-hoc-SQL-Anweisungen aus Sicherheits-, Wartungs- und Updataability-Gründen. Andere bevorzugen ad-hoc SQL-Anweisungen eifrig für ihre Flexibilität. In meiner eigenen Arbeit favoriere ich gespeicherte Prozeduren gegenüber Ad-hoc-SQL-Anweisungen, aber entschied mich, ad-hoc SQL-Anweisungen zu verwenden, um die früheren Lernprogramme zu vereinfachen.
Wenn Sie ein TableAdapter-Objekt definieren oder neue Methoden hinzufügen, erleichtert der TableAdapter-Assistent das Erstellen neuer gespeicherter Prozeduren oder die Verwendung vorhandener gespeicherter Prozeduren wie die Verwendung von Ad-hoc-SQL-Anweisungen. In diesem Tutorial untersuchen wir, wie der Assistent des TableAdapter gespeicherte Prozeduren automatisch generiert. Im nächsten Lernprogramm erfahren Sie, wie Sie die TableAdapter-Methoden so konfigurieren, dass vorhandene oder manuell erstellte gespeicherte Prozeduren verwendet werden.
Hinweis
Sehen Sie sich Rob Howards Blogeintrag "Nicht schon gespeicherte Prozeduren verwenden?" und Frans Boumas Blogeintrag "Gespeicherte Prozeduren sind schlecht, oder M Kay?" an, um eine lebhafte Debatte über die Vor- und Nachteile gespeicherter Prozeduren und ad-hoc SQL zu führen.
Grundlagen der gespeicherten Prozedur
Funktionen sind ein Konstrukt, das allen Programmiersprachen gemeinsam ist. Eine Funktion ist eine Auflistung von Anweisungen, die ausgeführt werden, wenn die Funktion aufgerufen wird. Funktionen können Eingabeparameter akzeptieren und optional einen Wert zurückgeben.
Gespeicherte Prozeduren sind Datenbankkonstrukte, die viele Ähnlichkeiten mit Funktionen in Programmiersprachen aufweisen. Eine gespeicherte Prozedur besteht aus einer Reihe von T-SQL-Anweisungen, die ausgeführt werden, wenn die gespeicherte Prozedur aufgerufen wird. Eine gespeicherte Prozedur akzeptiert möglicherweise null für viele Eingabeparameter und kann skalare Werte, Ausgabeparameter oder am häufigsten Resultsets aus SELECT
Abfragen zurückgeben.
Hinweis
Gespeicherte Prozeduren werden häufig als sprocs oder SPs bezeichnet.
Gespeicherte Prozeduren werden mithilfe der CREATE PROCEDURE
T-SQL-Anweisung erstellt. Das folgende T-SQL-Skript erstellt zum Beispiel eine gespeicherte Prozedur mit dem Namen GetProductsByCategoryID
, die einen einzelnen Parameter mit dem Namen @CategoryID
annimmt und die Felder ProductID
, ProductName
, UnitPrice
und Discontinued
der Spalten in der Products
-Tabelle zurückgibt, die einen übereinstimmenden CategoryID
-Wert aufweisen.
CREATE PROCEDURE GetProductsByCategoryID
(
@CategoryID int
)
AS
SELECT ProductID, ProductName, UnitPrice, Discontinued
FROM Products
WHERE CategoryID = @CategoryID
Nachdem diese gespeicherte Prozedur erstellt wurde, kann sie mithilfe der folgenden Syntax aufgerufen werden:
EXEC GetProductsByCategory categoryID
Hinweis
Im nächsten Lernprogramm untersuchen wir das Erstellen gespeicherter Prozeduren über die Visual Studio-IDE. In diesem Lernprogramm werden wir jedoch zulassen, dass der TableAdapter-Assistent automatisch die gespeicherten Prozeduren für uns generiert.
Zusätzlich zum einfachen Zurückgeben von Daten werden gespeicherte Prozeduren häufig verwendet, um mehrere Datenbankbefehle im Bereich einer einzelnen Transaktion auszuführen. Eine gespeicherte Prozedur mit dem Namen DeleteCategory
, z. B. kann einen @CategoryID
Parameter annehmen und zwei DELETE
Anweisungen ausführen: zuerst, eine zum Löschen der zugehörigen Produkte und eine zweite, die die angegebene Kategorie löscht. Mehrere Anweisungen innerhalb einer gespeicherten Prozedur werden nicht automatisch in eine Transaktion eingeschlossen. Zusätzliche T-SQL-Befehle müssen ausgegeben werden, um sicherzustellen, dass die mehrere Befehle der gespeicherten Prozedur als atomer Vorgang behandelt werden. Im nächsten Tutorial sehen wir uns an, wie man die Befehle einer gespeicherten Prozedur im Bereich einer Transaktion umschließt.
Wenn Sie gespeicherte Prozeduren innerhalb einer Architektur verwenden, rufen die Methoden der Data Access Layer eine bestimmte gespeicherte Prozedur auf, anstatt eine Ad-hoc-SQL-Anweisung auszugeben. Dadurch wird der Speicherort der ausgeführten SQL-Anweisungen (in der Datenbank) zentralisiert, anstatt sie innerhalb der Anwendungsarchitektur definiert zu haben. Diese Zentralisierung erleichtert das Auffinden, Analysieren und Optimieren der Abfragen und bietet ein viel klareres Bild darüber, wo und wie die Datenbank verwendet wird.
Weitere Informationen zu den Grundlagen gespeicherter Prozeduren finden Sie im Abschnitt "Weiteres Lesen" am Ende dieses Lernprogramms.
Schritt 1: Erstellen der Webseiten für erweiterte Datenzugriffsschichtszenarien
Bevor wir mit der Erstellung eines DAL mit gespeicherte Prozeduren beginnen, nutzen wir die Gelegenheit, die ASP.NET-Seiten in unserem Webprojekt zu erstellen, die wir dafür und die nächsten Tutorials benötigen. Beginnen Sie mit dem Hinzufügen eines neuen Ordners mit dem Namen AdvancedDAL
. Fügen Sie als Nächstes die folgenden ASP.NET Seiten zu diesem Ordner hinzu, und stellen Sie sicher, dass jede Seite der Site.master
Gestaltungsvorlage zugeordnet wird:
Default.aspx
NewSprocs.aspx
ExistingSprocs.aspx
JOINs.aspx
AddingColumns.aspx
ComputedColumns.aspx
EncryptingConfigSections.aspx
ManagedFunctionsAndSprocs.aspx
Abbildung 1: Hinzufügen der ASP.NET Seiten für die Lernprogramme für erweiterte Datenzugriffsschichtszenarien
Wie in den anderen Ordnern Default.aspx
werden im AdvancedDAL
Ordner die Tutorials im zugehörigen Abschnitt aufgelistet. Erinnern Sie sich daran, dass das SectionLevelTutorialListing.ascx
Benutzersteuerelement diese Funktionalität bereitstellt. Fügen Sie dieses Benutzersteuerelement zu Default.aspx
hinzu, indem Sie es aus dem Projektmappen-Explorer auf die Entwurfsansicht der Seite ziehen.
Abbildung 2: Hinzufügen des SectionLevelTutorialListing.ascx
Benutzersteuerelements zu Default.aspx
(Klicken, um das Bild in voller Größe anzuzeigen)
Fügen Sie diese Seiten schließlich als Einträge zur Web.sitemap
Datei hinzu. Fügen Sie insbesondere das folgende Markup nach dem Arbeiten mit Batchdaten <siteMapNode>
hinzu:
<siteMapNode url="~/AdvancedDAL/Default.aspx"
title="Advanced DAL Scenarios"
description="Explore a number of advanced Data Access Layer scenarios.">
<siteMapNode url="~/AdvancedDAL/NewSprocs.aspx"
title="Creating New Stored Procedures for TableAdapters"
description="Learn how to have the TableAdapter wizard automatically
create and use stored procedures." />
<siteMapNode url="~/AdvancedDAL/ExistingSprocs.aspx"
title="Using Existing Stored Procedures for TableAdapters"
description="See how to plug existing stored procedures into a
TableAdapter." />
<siteMapNode url="~/AdvancedDAL/JOINs.aspx"
title="Returning Data Using JOINs"
description="Learn how to augment your DataTables to work with data
returned from multiple tables via a JOIN query." />
<siteMapNode url="~/AdvancedDAL/AddingColumns.aspx"
title="Adding DataColumns to a DataTable"
description="Master adding new columns to an existing DataTable." />
<siteMapNode url="~/AdvancedDAL/ComputedColumns.aspx"
title="Working with Computed Columns"
description="Explore how to work with computed columns when using
Typed DataSets." />
<siteMapNode url="~/AdvancedDAL/EncryptingConfigSections.aspx"
title="Protected Connection Strings in Web.config"
description="Protect your connection string information in
Web.config using encryption." />
<siteMapNode url="~/AdvancedDAL/ManagedFunctionsAndSprocs.aspx"
title="Creating Managed SQL Functions and Stored Procedures"
description="See how to create SQL functions and stored procedures
using managed code." />
</siteMapNode>
Nehmen Sie sich nach dem Aktualisieren Web.sitemap
einen Moment Zeit, um die Tutorials-Website in einem Browser zu betrachten. Das Menü auf der linken Seite enthält jetzt Elemente für die lernprogramme für erweiterte DAL-Szenarien.
Abbildung 3: Die Websiteübersicht enthält jetzt Einträge für die Lernprogramme für erweiterte DAL-Szenarien.
Schritt 2: Konfigurieren eines TableAdapters zum Erstellen neuer gespeicherter Prozeduren
Um das Erstellen einer Datenzugriffsebene zu veranschaulichen, die gespeicherte Prozeduren anstelle von Ad-hoc-SQL-Anweisungen verwendet, erstellen wir ein neues Typd DataSet im ~/App_Code/DAL
Ordner namens NorthwindWithSprocs.xsd
. Da wir diesen Prozess in früheren Lernprogrammen ausführlich durchlaufen haben, werden wir die hier beschriebenen Schritte schnell durchlaufen. Wenn Sie beim Erstellen und Konfigurieren eines typisierten DataSets auf Schwierigkeiten stoßen oder weitere schrittweise Anleitungen benötigen, können Sie das Lernprogramm "Erstellen einer Datenzugriffsschicht" erneut konsultieren.
Fügen Sie dem Projekt ein neues DataSet hinzu, indem Sie mit der rechten Maustaste auf den DAL
Ordner klicken, "Neues Element hinzufügen" auswählen und die DataSet-Vorlage wie in Abbildung 4 dargestellt auswählen.
Abbildung 4: Ein neues typisiertes DataSet mit dem Namen NorthwindWithSprocs.xsd
zum Projekt hinzufügen (Klicken Sie, um das Bild in voller Größe anzusehen)
Dadurch wird das neue Typed DataSet erstellt, sein Designer geöffnet, ein neues TableAdapter erstellt und der TableAdapter-Konfigurations-Assistent gestartet. Der Erste Schritt des TableAdapter-Konfigurations-Assistenten fordert uns auf, die Datenbank auszuwählen, mit der sie arbeiten soll. Die Verbindungszeichenfolge zur Northwind-Datenbank sollte in der Dropdown-Liste aufgeführt werden. Wählen Sie dies aus, und klicken Sie auf "Weiter".
Auf diesem nächsten Bildschirm können wir auswählen, wie das TableAdapter-Objekt auf die Datenbank zugreifen soll. In früheren Lernprogrammen haben wir die erste Option "SQL-Anweisungen verwenden" ausgewählt. Wählen Sie für dieses Lernprogramm die zweite Option aus, erstellen Sie neue gespeicherte Prozeduren, und klicken Sie auf "Weiter".
Abbildung 5: Weisen Sie "TableAdapter" an, neue gespeicherte Prozeduren zu erstellen (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Genau wie bei der Verwendung von Ad-hoc-SQL-Anweisungen werden wir im folgenden Schritt aufgefordert, die SELECT
Anweisung für die TableAdapter-Hauptabfrage anzugeben. Anstatt jedoch die SELECT
hier eingegebene Anweisung zum direkten Ausführen einer Ad-hoc-Abfrage zu verwenden, erstellt der TableAdapter-Assistent eine gespeicherte Prozedur, die diese SELECT
Abfrage enthält.
Verwenden Sie die folgende SELECT
Abfrage für diesen TableAdapter:
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued
FROM Products
Abbildung 6: Eingeben der SELECT
Abfrage (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Hinweis
Die oben genannte Abfrage unterscheidet sich geringfügig von der Hauptabfrage des ProductsTableAdapter
im Northwind
typierten DataSet. Erinnern Sie sich daran, dass der ProductsTableAdapter
Datensatztyp im Northwind
zwei korrelierte Unterabfragen enthält, um den Kategorienamen und den Firmennamen für die Produktkategorie und jeden Lieferanten zurückzugeben. Im bevorstehenden Update des TableAdapter to Use JOINs-Lernprogramms werden wir uns ansehen, wie wir diese zugehörigen Daten zu diesem TableAdapter hinzufügen.
Nehmen Sie sich einen Moment Zeit, um auf die Schaltfläche "Erweiterte Optionen" zu klicken. Von hier aus können wir angeben, ob der Assistent auch Einfüge-, Update- und Löschanweisungen für den TableAdapter generieren soll, ob optimistische Parallelität verwendet werden soll und ob die Datentabelle nach Einfügungen und Aktualisierungen aktualisiert werden soll. Die Option "Einfüge-, Aktualisierungs- und Löschanweisungen generieren" ist standardmäßig aktiviert. Lassen Sie es aktiviert. Lassen Sie in diesem Tutorial die Option "Optimistische Parallelität verwenden" deaktiviert.
Wenn die gespeicherten Prozeduren automatisch vom TableAdapter-Assistenten erstellt werden, wird die Option "Datentabelle aktualisieren" ignoriert. Unabhängig davon, ob dieses Kontrollkästchen aktiviert ist, rufen die resultierenden einzufügenden und aktualisierten gespeicherten Prozeduren den just eingefügten oder just aktualisierten Datensatz ab, wie in Schritt 3 dargestellt.
Abbildung 7: Option „Generieren von Einfüge-, Aktualisierungs- und Löschanweisungen aktiviert lassen“
Hinweis
Wenn die Option "Optimistische Parallelität verwenden" aktiviert ist, fügt der Assistent der WHERE
Klausel zusätzliche Bedingungen hinzu, die verhindern, dass Daten aktualisiert werden, wenn Änderungen in anderen Feldern vorgenommen wurden. Weitere Informationen zur Verwendung des eingebauten Features zur optimistischen Parallelitätssteuerung des TableAdapters finden Sie im Tutorial zur Implementierung von Optimistischer Parallelität.
Nachdem Sie die SELECT
Abfrage eingegeben und bestätigt haben, dass die Option "Einfügen", "Aktualisieren" und "Löschen" aktiviert ist, klicken Sie auf "Weiter". Dieser nächste Bildschirm, der in Abbildung 8 gezeigt wird, fordert die Namen der gespeicherten Prozeduren auf, die der Assistent zum Auswählen, Einfügen, Aktualisieren und Löschen von Daten erstellt. Ändern Sie die Namen dieser gespeicherten Prozeduren in Products_Select
, , Products_Insert
, Products_Update
und Products_Delete
.
Abbildung 8: Umbenennen der gespeicherten Prozeduren (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Um das T-SQL zu sehen, das der TableAdapter-Assistent verwendet, um die vier gespeicherten Prozeduren zu erstellen, klicken Sie auf die Schaltfläche "SQL-Skriptvorschau". Im Dialogfeld "SQL-Skriptvorschau" können Sie das Skript in einer Datei speichern oder in die Zwischenablage kopieren.
Abbildung 9: Anzeigen einer Vorschau des ZUM Generieren der gespeicherten Prozeduren verwendeten SQL-Skripts
Klicken Sie nach dem Benennen der gespeicherten Prozeduren auf "Weiter", um die entsprechenden Methoden des TableAdapters zu benennen. Genau wie bei der Verwendung von Ad-hoc-SQL-Anweisungen können wir Methoden erstellen, die eine vorhandene DataTable ausfüllen oder eine neue zurückgeben. Wir können auch angeben, ob das TableAdapter das DB-Direct Muster zum Einfügen, Aktualisieren und Löschen von Datensätzen enthalten soll. Lassen Sie alle drei Kontrollkästchen aktiviert, benennen Sie jedoch die Methode „Return a DataTable“ in GetProducts
um, wie in Abbildung 10 zu sehen ist.
Abbildung 10: Benennen sie die Methoden Fill
und GetProducts
(Klicken Sie, um das Bild in voller Größe anzuzeigen)
Klicken Sie auf "Weiter", um eine Zusammenfassung der Schritte zu sehen, die der Assistent ausführen wird. Schließen Sie den Assistenten ab, indem Sie auf die Schaltfläche "Fertig stellen" klicken. Sobald der Assistent abgeschlossen ist, kehren Sie zum DataSet-Designer zurück, der jetzt die ProductsDataTable
enthalten sollte.
Abbildung 11: Der DataSet-Designer zeigt das neu hinzugefügte ProductsDataTable
Bild an (Klicken, um das Bild in voller Größe anzuzeigen)
Schritt 3: Untersuchen der neu erstellten gespeicherten Prozeduren
Der in Schritt 2 verwendete TableAdapter-Assistent erstellt automatisch die gespeicherten Prozeduren zum Auswählen, Einfügen, Aktualisieren und Löschen von Daten. Diese gespeicherten Prozeduren können über Visual Studio angezeigt oder geändert werden, indem Sie zum Server-Explorer wechseln und einen Drilldown in den Ordner "Gespeicherte Prozeduren" der Datenbank ausführen. Wie in Abbildung 12 dargestellt, enthält die Northwind-Datenbank vier neue gespeicherte Prozeduren: Products_Delete
, , , Products_Insert
Products_Select
und Products_Update
.
Abbildung 12: Die vier gespeicherten Prozeduren, die in Schritt 2 erstellt wurden, finden Sie im Ordner "Gespeicherte Prozeduren" der Datenbank.
Hinweis
Wenn der Server-Explorer nicht angezeigt wird, wechseln Sie zum Menü "Ansicht", und wählen Sie die Option "Server-Explorer" aus. Wenn die in Schritt 2 hinzugefügten produktbezogenen gespeicherten Prozeduren nicht angezeigt werden, klicken Sie mit der rechten Maustaste auf den Ordner "Gespeicherte Prozeduren", und wählen Sie "Aktualisieren" aus.
Um eine gespeicherte Prozedur anzuzeigen oder zu ändern, doppelklicken Sie im Server-Explorer auf den Namen, oder klicken Sie alternativ mit der rechten Maustaste auf die gespeicherte Prozedur, und wählen Sie "Öffnen" aus. Abbildung 13 zeigt die Products_Delete
gespeicherte Prozedur beim Öffnen.
Abbildung 13: Gespeicherte Prozeduren können in Visual Studio geöffnet und geändert werden (Klicken, um das Bild in voller Größe anzuzeigen)
Der Inhalt sowohl der Products_Delete
- als auch der Products_Select
-gespeicherten Prozeduren ist recht einfach zu verstehen. Die Products_Insert
- und Products_Update
-Prozeduren hingegen erfordern eine genauere Prüfung, da beide eine SELECT
-Anweisung nach ihren INSERT
- und UPDATE
-Anweisungen ausführen. Die folgende SQL-Datei besteht beispielsweise aus der Products_Insert
gespeicherten Prozedur:
ALTER PROCEDURE dbo.Products_Insert
(
@ProductName nvarchar(40),
@SupplierID int,
@CategoryID int,
@QuantityPerUnit nvarchar(20),
@UnitPrice money,
@UnitsInStock smallint,
@UnitsOnOrder smallint,
@ReorderLevel smallint,
@Discontinued bit
)
AS
SET NOCOUNT OFF;
INSERT INTO [Products] ([ProductName], [SupplierID], [CategoryID], [QuantityPerUnit],
[UnitPrice], [UnitsInStock], [UnitsOnOrder], [ReorderLevel], [Discontinued])
VALUES (@ProductName, @SupplierID, @CategoryID, @QuantityPerUnit, @UnitPrice,
@UnitsInStock, @UnitsOnOrder, @ReorderLevel, @Discontinued);
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice,
UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued
FROM Products
WHERE (ProductID = SCOPE_IDENTITY())
Die gespeicherte Prozedur akzeptiert als Eingabeparameter die Spalten, die von der im TableAdapter-Assistenten angegebenen Abfrage Products
zurückgegeben wurden, und diese Werte werden in einer SELECT
Anweisung verwendet. Nach der INSERT
Anweisung wird eine SELECT
Abfrage verwendet, um die Products
Spaltenwerte (einschließlich des ProductID
) des neu hinzugefügten Datensatzes zurückzugeben. Diese Aktualisierungsfunktion ist hilfreich beim Hinzufügen eines neuen Datensatzes mithilfe des Batchaktualisierungsmusters, da die neu hinzugefügten ProductRow
ProductID
Instanzeneigenschaften automatisch mit den automatisch erhöhten Werten aktualisiert werden, die der Datenbank zugewiesen wurden.
Der folgende Code veranschaulicht dieses Feature. Es enthält ein ProductsTableAdapter
und ProductsDataTable
erstellt für das typisierte NorthwindWithSprocs
DataSet. Der Datenbank wird ein neues Produkt hinzugefügt, indem eine ProductsRow
Instanz erstellt wird, deren Werte bereitgestellt werden. Die TableAdapter-Methode Update
wird aufgerufen, wobei die ProductsDataTable
übergeben wird. Intern listet die TableAdapter-Methode Update
die ProductsRow
Instanzen in der übergebenen DataTable auf (in diesem Beispiel gibt es nur eine - die gerade hinzugefügte) und führt den entsprechenden Einfüge-, Aktualisierungs- oder Löschbefehl aus. In diesem Fall wird die Products_Insert
gespeicherte Prozedur ausgeführt, die der Products
Tabelle einen neuen Datensatz hinzufügt und die Details des neu hinzugefügten Datensatzes zurückgibt. Der Wert der ProductsRow
Instanz ProductID
wird dann aktualisiert. Nachdem die Update
Methode abgeschlossen wurde, können wir über die ProductID
Eigenschaft s ProductsRow
auf den neu hinzugefügten ProductID
Datensatzwert zugreifen.
' Create the ProductsTableAdapter and ProductsDataTable
Dim productsAPI As New NorthwindWithSprocsTableAdapters.ProductsTableAdapter
Dim products As New NorthwindWithSprocs.ProductsDataTable
' Create a new ProductsRow instance and set its properties
Dim product As NorthwindWithSprocs.ProductsRow = products.NewProductsRow()
product.ProductName = "New Product"
product.CategoryID = 1 ' Beverages
product.Discontinued = False
' Add the ProductsRow instance to the DataTable
products.AddProductsRow(product)
' Update the DataTable using the Batch Update pattern
productsAPI.Update(products)
' At this point, we can determine the value of the newly-added record's ProductID
Dim newlyAddedProductIDValue as Integer = product.ProductID
Die Products_Update
gespeicherte Prozedur enthält ebenso eine SELECT
Anweisung nach ihrer UPDATE
Anweisung.
ALTER PROCEDURE dbo.Products_Update
(
@ProductName nvarchar(40),
@SupplierID int,
@CategoryID int,
@QuantityPerUnit nvarchar(20),
@UnitPrice money,
@UnitsInStock smallint,
@UnitsOnOrder smallint,
@ReorderLevel smallint,
@Discontinued bit,
@Original_ProductID int,
@ProductID int
)
AS
SET NOCOUNT OFF;
UPDATE [Products]
SET [ProductName] = @ProductName, [SupplierID] = @SupplierID,
[CategoryID] = @CategoryID, [QuantityPerUnit] = @QuantityPerUnit,
[UnitPrice] = @UnitPrice, [UnitsInStock] = @UnitsInStock,
[UnitsOnOrder] = @UnitsOnOrder, [ReorderLevel] = @ReorderLevel,
[Discontinued] = @Discontinued
WHERE (([ProductID] = @Original_ProductID));
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued
FROM Products
WHERE (ProductID = @ProductID)
Beachten Sie, dass diese gespeicherte Prozedur zwei Eingabeparameter für ProductID
enthält: @Original_ProductID
und @ProductID
. Diese Funktionalität ermöglicht Szenarien, in denen der Primärschlüssel möglicherweise geändert wird. In einer Mitarbeiterdatenbank kann jeder Mitarbeiterdatensatz beispielsweise die Sozialversicherungsnummer des Mitarbeiters als Primärschlüssel verwenden. Um die Sozialversicherungsnummer eines vorhandenen Arbeitnehmers zu ändern, müssen sowohl die neue Sozialversicherungsnummer als auch die ursprüngliche nummer angegeben werden. Für die Products
Tabelle ist diese Funktionalität nicht erforderlich, da es sich bei der ProductID
Spalte um eine IDENTITY
Spalte handelt und nie geändert werden sollte. Tatsächlich wird in der UPDATE
Anweisung der Products_Update
gespeicherten Prozedur die Spalte nicht in der ProductID
Spaltenliste aufgeführt. Während @Original_ProductID
in der UPDATE
Anweisungsklausel WHERE
verwendet wird, ist diese für die Products
Tabelle überflüssig und könnte durch den @ProductID
Parameter ersetzt werden. Beim Ändern der Parameter einer gespeicherten Prozedur ist es wichtig, dass auch die TableAdapter-Methode(n) aktualisiert wird, die diese gespeicherte Prozedur verwendet.
Schritt 4: Ändern der Parameter einer gespeicherten Prozedur und Aktualisieren des TableAdapter
Da der @Original_ProductID
Parameter überflüssig ist, entfernen wir ihn vollständig aus der Products_Update
gespeicherten Prozedur. Öffnen Sie die gespeicherte Prozedur Products_Update
, löschen Sie den Parameter @Original_ProductID
, und ändern Sie in der Klausel WHERE
der Anweisung UPDATE
den verwendeten Parameternamen von @Original_ProductID
zu @ProductID
. Nachdem Sie diese Änderungen vorgenommen haben, sollte die T-SQL innerhalb der gespeicherten Prozedur wie folgt aussehen:
ALTER PROCEDURE dbo.Products_Update
(
@ProductName nvarchar(40),
@SupplierID int,
@CategoryID int,
@QuantityPerUnit nvarchar(20),
@UnitPrice money,
@UnitsInStock smallint,
@UnitsOnOrder smallint,
@ReorderLevel smallint,
@Discontinued bit,
@ProductID int
)
AS
SET NOCOUNT OFF;
UPDATE [Products] SET [ProductName] = @ProductName, [SupplierID] = @SupplierID,
[CategoryID] = @CategoryID, [QuantityPerUnit] = @QuantityPerUnit,
[UnitPrice] = @UnitPrice, [UnitsInStock] = @UnitsInStock,
[UnitsOnOrder] = @UnitsOnOrder, [ReorderLevel] = @ReorderLevel,
[Discontinued] = @Discontinued
WHERE (([ProductID] = @ProductID));
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued
FROM Products
WHERE (ProductID = @ProductID)
Wenn Sie diese Änderungen in der Datenbank speichern möchten, klicken Sie auf das Symbol "Speichern" in der Symbolleiste, oder drücken Sie STRG+S. Momentan erwartet die gespeicherte Prozedur Products_Update
keinen Eingabeparameter, aber der TableAdapter ist so konfiguriert, dass ein solcher Parameter übergeben wird. Sie können die Parameter sehen, die der TableAdapter an die gespeicherte Prozedur Products_Update
sendet, indem Sie den TableAdapter im DataSet-Designer auswählen, zum Eigenschaftenfenster wechseln und auf die Auslassungspunkte in der UpdateCommand
Parameters
Sammlung klicken. Dadurch wird das Dialogfeld "Parametersammlungs-Editor" in Abbildung 14 angezeigt.
Abbildung 14: Der Parameter-Editor listet die Parameter auf, die an die gespeicherte Prozedur übergeben werden.
Sie können diesen Parameter hier entfernen, indem Sie einfach den @Original_ProductID
Parameter aus der Liste der Mitglieder auswählen und auf die Schaltfläche "Entfernen" klicken.
Alternativ können Sie die für alle Methoden verwendeten Parameter aktualisieren, indem Sie im Designer mit der rechten Maustaste auf den TableAdapter klicken und dann "Konfigurieren" auswählen. Dadurch wird der TableAdapter-Konfigurations-Assistent geöffnet, welcher die gespeicherten Prozeduren für Auswahl, Einfügen, Aktualisieren und Löschen sowie die Parameter auflistet, die diese Prozeduren empfangen sollen. Wenn Sie auf die Dropdownliste "Aktualisieren" klicken, können Sie die erwarteten Eingabeparameter der Products_Update
gespeicherten Prozeduren sehen, die nun @Original_ProductID
nicht mehr enthalten (siehe Abbildung 15). Klicken Sie einfach auf "Fertig stellen", um die vom TableAdapter verwendete Parameterauflistung automatisch zu aktualisieren.
Abbildung 15: Sie können alternativ den Konfigurations-Assistenten für TableAdapter verwenden, um die Methodenparameterauflistungen zu aktualisieren (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Schritt 5: Hinzufügen zusätzlicher TableAdapter-Methoden
Wie Schritt 2 veranschaulicht, ist es beim Erstellen eines neuen TableAdapter einfach, die entsprechenden gespeicherten Prozeduren automatisch zu generieren. Das gleiche gilt beim Hinzufügen zusätzlicher Methoden zu einem TableAdapter. Um dies zu veranschaulichen, fügen wir der GetProductByProductID(productID)
in Schritt 2 erstellten Methode eine ProductsTableAdapter
Methode hinzu. Diese Methode verwendet als Eingabewert ProductID
und gibt Details zum angegebenen Produkt zurück.
Klicken Sie zunächst mit der rechten Maustaste auf das TableAdapter-Objekt, und wählen Sie im Kontextmenü "Abfrage hinzufügen" aus.
Abbildung 16: Hinzufügen einer neuen Abfrage zum TableAdapter
Dadurch wird der Assistent zur Konfiguration der TableAdapter-Abfragen gestartet, der zuerst fragt, wie der TableAdapter auf die Datenbank zugreifen soll. Um eine neue gespeicherte Prozedur zu erstellen, wählen Sie die Option "Neue gespeicherte Prozedur erstellen" aus, und klicken Sie auf "Weiter".
Abbildung 17: Auswählen der Option "Neue gespeicherte Prozedur erstellen" (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Der nächste Bildschirm fordert uns auf, den auszuführenden Abfragetyp zu identifizieren, ob er eine Zeilenmenge oder einen einzelnen skalaren Wert zurückgibt oder eine UPDATE
, INSERT
oder DELETE
Anweisung ausführt. Da die GetProductByProductID(productID)
Methode eine Zeile zurückgibt, behalten Sie die SELECT-Eigenschaft bei, die die Ausgewählte Zeilenoption zurückgibt, und drücken Sie "Weiter".
Abbildung 18: Wählen Sie das SELECT, das die Zeilenoption zurückgibt (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Der nächste Bildschirm zeigt die TableAdapter-Hauptabfrage an, die nur den Namen der gespeicherten Prozedur (dbo.Products_Select
) auflistet. Ersetzen Sie den Namen der gespeicherten Prozedur durch die folgende SELECT
Anweisung, die alle Produktfelder für ein angegebenes Produkt zurückgibt:
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued
FROM Products
WHERE ProductID = @ProductID
Abbildung 19: Ersetzen des Namens der gespeicherten Prozedur durch eine SELECT
Abfrage (Klicken, um das Bild in voller Größe anzuzeigen)
Im folgenden Bildschirm werden Sie aufgefordert, die gespeicherte Prozedur zu benennen, die erstellt wird. Geben Sie den Namen Products_SelectByProductID
ein, und klicken Sie auf "Weiter".
Abbildung 20: Benennen der neuen gespeicherten Prozedur Products_SelectByProductID
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Der letzte Schritt des Assistenten ermöglicht es uns, die generierten Methodennamen zu ändern und anzugeben, ob das Muster "Datentabelle ausfüllen", "DataTable-Muster zurückgeben" oder beides verwendet werden soll. Lassen Sie für diese Methode beide Optionen aktiviert, aber benennen Sie die Methoden in FillByProductID
und GetProductByProductID
um. Klicken Sie auf "Weiter", um eine Zusammenfassung der Schritte anzuzeigen, die der Assistent ausführt, und klicken Sie dann auf "Fertigstellen", um den Assistenten abzuschließen.
Abbildung 21: Umbenennen der TableAdapter-Methoden in FillByProductID
und GetProductByProductID
(Zum Anzeigen des Bilds mit voller Größe klicken)
Nach Abschluss des Assistenten steht dem TableAdapter eine neue Methode zur Verfügung, GetProductByProductID(productID)
, die die gerade erstellte gespeicherte Prozedur Products_SelectByProductID
beim Aufrufen ausführt. Nehmen Sie sich einen Moment Zeit, um diese neue gespeicherte Prozedur aus dem Server-Explorer anzuzeigen, indem Sie in den Ordner "Gespeicherte Prozeduren" drillen und öffnen Products_SelectByProductID
(wenn sie nicht angezeigt wird, klicken Sie mit der rechten Maustaste auf den Ordner "Gespeicherte Prozeduren", und wählen Sie "Aktualisieren" aus).
Beachten Sie, dass das gespeicherte Verfahren SelectByProductID
den Eingabeparameter @ProductID
verwendet und die Anweisung SELECT
ausführt, die wir im Assistenten eingegeben haben.
ALTER PROCEDURE dbo.Products_SelectByProductID
(
@ProductID int
)
AS
SET NOCOUNT ON;
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued
FROM Products
WHERE ProductID = @ProductID
Schritt 6: Erstellen einer Business Logic Layer-Klasse
In der gesamten Lernprogrammserie haben wir uns bemüht, eine mehrschichtige Architektur aufrechtzuerhalten, in der die Präsentationsschicht (Presentation Layer) alle ihre Aufrufe an die Geschäftslogikebene (Business Logic Layer, BLL) gerichtet hat. Um diese Entwurfsentscheidung einzuhalten, müssen wir zunächst eine BLL-Klasse für das neue Typd DataSet erstellen, bevor wir auf Produktdaten aus der Präsentationsebene zugreifen können.
Erstellen Sie eine neue Klassendatei namens ProductsBLLWithSprocs.vb
im ~/App_Code/BLL
Ordner, und fügen Sie sie dem folgenden Code hinzu:
Imports NorthwindWithSprocsTableAdapters
<System.ComponentModel.DataObject()> _
Public Class ProductsBLLWithSprocs
Private _productsAdapter As ProductsTableAdapter = Nothing
Protected ReadOnly Property Adapter() As ProductsTableAdapter
Get
If _productsAdapter Is Nothing Then
_productsAdapter = New ProductsTableAdapter()
End If
Return _productsAdapter
End Get
End Property
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Select, True)> _
Public Function GetProducts() As NorthwindWithSprocs.ProductsDataTable
Return Adapter.GetProducts()
End Function
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetProductByProductID(ByVal productID As Integer) _
As NorthwindWithSprocs.ProductsDataTable
Return Adapter.GetProductByProductID(productID)
End Function
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Insert, True)> _
Public Function AddProduct _
(ByVal productName As String, ByVal supplierID As Nullable(Of Integer), _
ByVal categoryID As Nullable(Of Integer), ByVal quantityPerUnit As String, _
ByVal unitPrice As Nullable(Of Decimal), _
ByVal unitsInStock As Nullable(Of Short), _
ByVal unitsOnOrder As Nullable(Of Short), _
ByVal reorderLevel As Nullable(Of Short), _
ByVal discontinued As Boolean) _
As Boolean
' Create a new ProductRow instance
Dim products As New NorthwindWithSprocs.ProductsDataTable()
Dim product As NorthwindWithSprocs.ProductsRow = products.NewProductsRow()
product.ProductName = productName
If Not supplierID.HasValue Then
product.SetSupplierIDNull()
Else
product.SupplierID = supplierID.Value
End If
If Not categoryID.HasValue Then
product.SetCategoryIDNull()
Else
product.CategoryID = categoryID.Value
End If
If quantityPerUnit Is Nothing Then
product.SetQuantityPerUnitNull()
Else
product.QuantityPerUnit = quantityPerUnit
End If
If Not unitPrice.HasValue Then
product.SetUnitPriceNull()
Else
product.UnitPrice = unitPrice.Value
End If
If Not unitsInStock.HasValue Then
product.SetUnitsInStockNull()
Else
product.UnitsInStock = unitsInStock.Value
End If
If Not unitsOnOrder.HasValue Then
product.SetUnitsOnOrderNull()
Else
product.UnitsOnOrder = unitsOnOrder.Value
End If
If Not reorderLevel.HasValue Then
product.SetReorderLevelNull()
Else
product.ReorderLevel = reorderLevel.Value
End If
product.Discontinued = discontinued
' Add the new product
products.AddProductsRow(product)
Dim rowsAffected As Integer = Adapter.Update(products)
' Return true if precisely one row was inserted, otherwise false
Return rowsAffected = 1
End Function
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Update, True)> _
Public Function UpdateProduct
(ByVal productName As String, ByVal supplierID As Nullable(Of Integer), _
ByVal categoryID As Nullable(Of Integer), ByVal quantityPerUnit As String, _
ByVal unitPrice As Nullable(Of Decimal), _
ByVal unitsInStock As Nullable(Of Short), _
ByVal unitsOnOrder As Nullable(Of Short), _
ByVal reorderLevel As Nullable(Of Short), _
ByVal discontinued As Boolean, ByVal productID As Integer) _
As Boolean
Dim products As NorthwindWithSprocs.ProductsDataTable = _
Adapter.GetProductByProductID(productID)
If products.Count = 0 Then
' no matching record found, return false
Return False
End If
Dim product As NorthwindWithSprocs.ProductsRow = products(0)
product.ProductName = productName
If Not supplierID.HasValue Then
product.SetSupplierIDNull()
Else
product.SupplierID = supplierID.Value
End If
If Not categoryID.HasValue Then
product.SetCategoryIDNull()
Else
product.CategoryID = categoryID.Value
End If
If quantityPerUnit Is Nothing Then
product.SetQuantityPerUnitNull()
Else
product.QuantityPerUnit = quantityPerUnit
End If
If Not unitPrice.HasValue Then
product.SetUnitPriceNull()
Else
product.UnitPrice = unitPrice.Value
End If
If Not unitsInStock.HasValue Then
product.SetUnitsInStockNull()
Else
product.UnitsInStock = unitsInStock.Value
End If
If Not unitsOnOrder.HasValue Then
product.SetUnitsOnOrderNull()
Else
product.UnitsOnOrder = unitsOnOrder.Value
End If
If Not reorderLevel.HasValue Then
product.SetReorderLevelNull()
Else
product.ReorderLevel = reorderLevel.Value
End If
product.Discontinued = discontinued
' Update the product record
Dim rowsAffected As Integer = Adapter.Update(product)
' Return true if precisely one row was updated, otherwise false
Return rowsAffected = 1
End Function
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Delete, True)> _
Public Function DeleteProduct(ByVal productID As Integer) As Boolean
Dim rowsAffected As Integer = Adapter.Delete(productID)
' Return true if precisely one row was deleted, otherwise false
Return rowsAffected = 1
End Function
End Class
Diese Klasse imitiert die ProductsBLL
-Klassensemantik aus früheren Lernprogrammen, verwendet jedoch die ProductsTableAdapter
und ProductsDataTable
Objekte aus dem NorthwindWithSprocs
DataSet. Statt z. B. eine Imports NorthwindTableAdapters
Anweisung am Anfang der Klassendatei zu haben, wie ProductsBLL
, verwendet die Klasse ProductsBLLWithSprocs
Imports NorthwindWithSprocsTableAdapters
. Ebenso werden die in dieser Klasse verwendeten Objekte ProductsDataTable
und ProductsRow
mit dem Namespace NorthwindWithSprocs
vorangestellt. Die ProductsBLLWithSprocs
Klasse bietet zwei Methoden für den Datenzugriff GetProducts
sowie GetProductByProductID
Methoden zum Hinzufügen, Aktualisieren und Löschen einer einzelnen Produktinstanz.
Schritt 7: Arbeiten mit demNorthwindWithSprocs
DataSet aus der Präsentationsebene
An diesem Punkt haben wir eine DAL erstellt, die gespeicherte Prozeduren verwendet, um auf die zugrunde liegenden Datenbankdaten zuzugreifen und sie zu ändern. Wir haben auch eine rudimentäre BLL mit Methoden erstellt, um alle Produkte oder ein bestimmtes Produkt zusammen mit Methoden zum Hinzufügen, Aktualisieren und Löschen von Produkten abzurufen. Zum Abrunden dieses Lernprogramms erstellen wir eine ASP.NET Seite, die die BLL-Klasse ProductsBLLWithSprocs
zum Anzeigen, Aktualisieren und Löschen von Datensätzen verwendet.
Öffnen Sie die NewSprocs.aspx
Seite im AdvancedDAL
Ordner, und ziehen Sie eine GridView aus der Toolbox auf den Designer, und nennen Sie sie Products
. Wählen Sie das Smarttag der GridView und binden Sie es an eine neue ObjectDataSource mit dem Namen ProductsDataSource
. Konfigurieren Sie die ObjectDataSource so, dass sie die ProductsBLLWithSprocs
Klasse verwendet, wie in Abbildung 22 dargestellt.
Abbildung 22: Konfigurieren der ObjectDataSource für die Verwendung der ProductsBLLWithSprocs
Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Die Dropdownliste auf der Registerkarte SELECT verfügt über zwei Optionen: GetProducts
und GetProductByProductID
. Da wir alle Produkte in GridView anzeigen möchten, wählen Sie die GetProducts
Methode aus. Die Dropdownlisten in den Registerkarten UPDATE, INSERT und DELETE weisen jeweils nur eine Methode auf. Stellen Sie sicher, dass jede dieser Dropdownlisten die entsprechende Methode ausgewählt hat, und klicken Sie dann auf "Fertig stellen".
Nachdem der ObjectDataSource-Assistent abgeschlossen wurde, fügt Visual Studio BoundFields und ein CheckBoxField zum GridView für die Produktdatenfelder hinzu. Aktivieren Sie die integrierten Funktionen zum Bearbeiten und Löschen von GridView, indem Sie die Optionen "Bearbeiten aktivieren" und "Löschen aktivieren" im Smarttag auswählen.
Abbildung 23: Die Seite enthält eine GridView mit aktivierter Bearbeitungs- und Löschunterstützung (Klicken, um das Bild in voller Größe anzuzeigen)
Wie wir in früheren Tutoren besprochen haben, legt Visual Studio nach Abschluss des Assistenten für ObjectDataSource die OldValuesParameterFormatString
Eigenschaft auf original_{0} fest. Dies muss auf den Standardwert {0} zurückgesetzt werden, damit die Funktionen zur Datenänderung ordnungsgemäß funktionieren, wenn die von den Methoden in unserer BLL erwarteten Parameter vorliegen. Stellen Sie daher sicher, dass die OldValuesParameterFormatString
-Eigenschaft auf {0} festgelegt oder vollständig aus der deklarativen Syntax entfernt wird.
Nachdem Sie den Assistenten zum Konfigurieren von Datenquellen abgeschlossen haben, die Bearbeitungs- und Löschfunktionen in GridView aktivieren und die OldValuesParameterFormatString
-Eigenschaft von ObjectDataSource auf ihren Standardwert zurücksetzen, sollte das deklarative Markup Ihrer Seite wie folgt aussehen:
<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
InsertVisible="False" ReadOnly="True"
SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName"
SortExpression="ProductName" />
<asp:BoundField DataField="SupplierID" HeaderText="SupplierID"
SortExpression="SupplierID" />
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
SortExpression="CategoryID" />
<asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit"
SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock"
SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder"
SortExpression="UnitsOnOrder" />
<asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel"
SortExpression="ReorderLevel" />
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
DeleteMethod="DeleteProduct" InsertMethod="AddProduct"
SelectMethod="GetProducts" TypeName="ProductsBLLWithSprocs"
UpdateMethod="UpdateProduct">
<DeleteParameters>
<asp:Parameter Name="productID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="supplierID" Type="Int32" />
<asp:Parameter Name="categoryID" Type="Int32" />
<asp:Parameter Name="quantityPerUnit" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="unitsInStock" Type="Int16" />
<asp:Parameter Name="unitsOnOrder" Type="Int16" />
<asp:Parameter Name="reorderLevel" Type="Int16" />
<asp:Parameter Name="discontinued" Type="Boolean" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="supplierID" Type="Int32" />
<asp:Parameter Name="categoryID" Type="Int32" />
<asp:Parameter Name="quantityPerUnit" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="unitsInStock" Type="Int16" />
<asp:Parameter Name="unitsOnOrder" Type="Int16" />
<asp:Parameter Name="reorderLevel" Type="Int16" />
<asp:Parameter Name="discontinued" Type="Boolean" />
</InsertParameters>
</asp:ObjectDataSource>
An diesem Punkt könnten wir die GridView aufräumen, indem wir die Bearbeitungsschnittstelle anpassen, einschließlich Validierung, und die CategoryID
- und SupplierID
-Spalten als DropDownLists rendern lassen usw. Wir könnten auch eine clientseitige Bestätigung zur Schaltfläche "Löschen" hinzufügen, und ich möchte Sie ermutigen, die Zeit zu nehmen, diese Verbesserungen zu implementieren. Da diese Themen in früheren Lernprogrammen behandelt wurden, werden wir sie hier jedoch nicht wieder behandeln.
Unabhängig davon, ob Sie die GridView verbessern oder nicht, testen Sie die Kernfunktionen der Seite in einem Browser. Wie in Abbildung 24 dargestellt, listet die Seite die Produkte in einer GridView auf, die die Bearbeitungs- und Löschfunktionen pro Zeile bereitstellt.
Abbildung 24: Die Produkte können aus der GridView angezeigt, bearbeitet und gelöscht werden (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Zusammenfassung
Die TableAdapter in einem typisierten DataSet können auf Daten aus der Datenbank zugreifen, indem sie ad-hoc-SQL-Anweisungen oder gespeicherte Prozeduren verwenden. Beim Arbeiten mit gespeicherten Prozeduren können vorhandene gespeicherte Prozeduren verwendet werden, oder der TableAdapter-Assistent kann angewiesen werden, neue gespeicherte Prozeduren basierend auf einer SELECT
Abfrage zu erstellen. In diesem Lernprogramm haben wir untersucht, wie die gespeicherten Prozeduren automatisch für uns erstellt werden.
Das automatische Generieren der gespeicherten Prozeduren hilft Zeit zu sparen, aber es gibt bestimmte Fälle, in denen die vom Assistenten erstellte gespeicherte Prozedur nicht übereinstimmt mit dem, was wir selbst erstellt hätten. Ein Beispiel ist die Products_Update
gespeicherte Prozedur, die sowohl Eingabeparameter @Original_ProductID
als auch @ProductID
erwartete, obwohl der @Original_ProductID
Parameter überflüssig war.
In vielen Szenarien wurden die gespeicherten Prozeduren möglicherweise bereits erstellt, oder wir möchten sie manuell erstellen, um eine bessere Kontrolle über die Befehle der gespeicherten Prozedur zu erhalten. In beiden Fällen möchten wir das TableAdapter anweisen, vorhandene gespeicherte Prozeduren für seine Methoden zu verwenden. Wir werden sehen, wie dies im nächsten Lernprogramm zu erreichen ist.
Glückliche Programmierung!
Weitere nützliche Informationen
Weitere Informationen zu den in diesem Lernprogramm erläuterten Themen finden Sie in den folgenden Ressourcen:
- Erstellen und Verwalten gespeicherter Prozeduren
- Gespeicherte Prozeduren: Eine Übersicht
- Erstellen einer gespeicherten Prozedur
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. Leitender Prüfer für dieses Lernprogramm war Hilton Geisenow. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.