Freigeben über


Erstellen von neuen gespeicherten Prozeduren für die TableAdapter-Steuerelemente des typisierten DataSet (VB)

von Scott Mitchell

PDF herunterladen

In früheren Tutorials haben wir SQL-Anweisungen in unserem Code erstellt und die Anweisungen an die auszuführende Datenbank übergeben. Ein alternativer Ansatz besteht darin, gespeicherte Prozeduren zu verwenden, bei denen die SQL-Anweisungen in der Datenbank vordefiniert sind. In diesem Tutorial erfahren Sie, wie Der TableAdapter-Assistent neue gespeicherte Prozeduren für uns generiert.

Einführung

Die Datenzugriffsebene (Data Access Layer, DAL) für diese Tutorials verwendet typisierte DataSets. Wie im Tutorial Erstellen einer Datenzugriffsebene 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-Schnittstelle mit der zugrunde liegenden Datenbank zur Ausführung des Datenzugriffs verwendet wird. Dies umfasst das Auffüllen der DataTables mit Daten, das Ausführen von Abfragen, die Skalardaten 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 SELECT columnList FROM TableNameoder gespeicherte Prozeduren sein. Die TableAdapters in unserer Architektur verwenden Ad-hoc-SQL-Anweisungen. Viele Entwickler und Datenbankadministratoren bevorzugen jedoch aus Gründen der Sicherheit, Verwaltbarkeit und Updataability gespeicherte Prozeduren gegenüber Ad-hoc-SQL-Anweisungen. Andere bevorzugen ad-hoc-SQL-Anweisungen aufgrund ihrer Flexibilität. In meiner eigenen Arbeit bevorzuge ich gespeicherte Prozeduren gegenüber Ad-hoc-SQL-Anweisungen, habe mich aber für die Verwendung von Ad-hoc-SQL-Anweisungen entschieden, um die vorherigen Tutorials zu vereinfachen.

Wenn Sie einen TableAdapter definieren oder neue Methoden hinzufügen, erleichtert der TableAdapter-Assistent das Erstellen neuer gespeicherter Prozeduren oder die Verwendung vorhandener gespeicherter Prozeduren ebenso wie die Verwendung von Ad-hoc-SQL-Anweisungen. In diesem Tutorial wird erläutert, wie der TableAdapter-Assistent gespeicherte Prozeduren automatisch generiert. Im nächsten Tutorial erfahren Sie, wie Sie die TableAdapter-Methoden für die Verwendung vorhandener oder manuell erstellter gespeicherter Prozeduren konfigurieren.

Hinweis

Lesen Sie Rob Howards Blogbeitrag Don t Use Stored Procedures Yet? und Frans Boumas Blogeintrag Gespeicherte Prozeduren sind schlecht, M Kay? für eine lebhafte Debatte über die Vor- und Nachteile von gespeicherten Prozeduren und ad-hoc SQL.

Grundlagen der gespeicherten Prozeduren

Funktionen sind ein Konstrukt, das für alle 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 haben. Eine gespeicherte Prozedur besteht aus einem Satz von T-SQL-Anweisungen, die ausgeführt werden, wenn die gespeicherte Prozedur aufgerufen wird. Eine gespeicherte Prozedur kann bis zu vielen Eingabeparametern null akzeptieren und Skalarwerte, 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 beispielsweise eine gespeicherte Prozedur namens GetProductsByCategoryID , die einen einzelnen Parameter namens @CategoryID akzeptiert und die ProductIDFelder , ProductName, UnitPriceund Discontinued der Spalten in der Tabelle zurückgibt, die Products 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 mit der folgenden Syntax aufgerufen werden:

EXEC GetProductsByCategory categoryID

Hinweis

Im nächsten Tutorial wird das Erstellen gespeicherter Prozeduren über die Visual Studio-IDE untersucht. Für dieses Tutorial wird der TableAdapter-Assistent jedoch die gespeicherten Prozeduren automatisch generieren lassen.

Neben der einfachen Rückgabe von Daten werden gespeicherte Prozeduren häufig verwendet, um mehrere Datenbankbefehle im Bereich einer einzelnen Transaktion auszuführen. Eine gespeicherte Prozedur namens DeleteCategorykann z. B. einen @CategoryID Parameter aufnehmen und zwei DELETE Anweisungen ausführen: erstens, 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 innerhalb einer Transaktion umschlossen. Es müssen zusätzliche T-SQL-Befehle ausgegeben werden, um sicherzustellen, dass mehrere Befehle der gespeicherten Prozedur als atomischer Vorgang behandelt werden. Im folgenden Tutorial erfahren Sie, wie Sie befehle einer gespeicherten Prozedur innerhalb des Bereichs einer Transaktion umschließen.

Wenn Sie gespeicherte Prozeduren innerhalb einer Architektur verwenden, rufen die Methoden der Datenzugriffsebene 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 ihn innerhalb der Anwendungsarchitektur zu definieren. Diese Zentralisierung erleichtert wohl das Auffinden, Analysieren und Optimieren der Abfragen und liefert ein viel klareres Bild darüber, wo und wie die Datenbank verwendet wird.

Weitere Informationen zu den Grundlagen gespeicherter Prozeduren finden Sie in den Ressourcen im Abschnitt Weitere Informationen am Ende dieses Tutorials.

Schritt 1: Erstellen der Erweiterten Datenzugriffsebenenszenarien-Webseiten

Bevor wir mit der Diskussion zum Erstellen einer DAL mithilfe gespeicherter Prozeduren beginnen, nehmen wir uns zunächst einen Moment Zeit, um die ASP.NET Seiten in unserem Websiteprojekt zu erstellen, die wir für dies und die nächsten Tutorials benötigen. Fügen Sie zunächst einen neuen Ordner mit dem Namen hinzu AdvancedDAL. Fügen Sie als Nächstes die folgenden ASP.NET Seiten zu diesem Ordner hinzu, und stellen Sie sicher, dass Sie jede Seite der Site.master master Seite zuordnen:

  • Default.aspx
  • NewSprocs.aspx
  • ExistingSprocs.aspx
  • JOINs.aspx
  • AddingColumns.aspx
  • ComputedColumns.aspx
  • EncryptingConfigSections.aspx
  • ManagedFunctionsAndSprocs.aspx

Hinzufügen der ASP.NET Pages für die Tutorials für erweiterte Datenzugriffsebenenszenarien

Abbildung 1: Hinzufügen der ASP.NET Pages für die Tutorials für erweiterte Datenzugriffsebenenszenarien

Wie in den anderen Ordnern Default.aspx listet der AdvancedDAL Ordner die Tutorials in seinem Abschnitt auf. Denken Sie daran, dass das SectionLevelTutorialListing.ascx Benutzersteuerelement diese Funktionalität bereitstellt. Fügen Sie daher dieses Benutzersteuerelement zu Default.aspx hinzu, indem Sie es vom Projektmappen-Explorer in die Entwurfsansicht der Seite ziehen.

Hinzufügen des SectionLevelTutorialListing.ascx-Benutzersteuerelements zu Default.aspx

Abbildung 2: Hinzufügen des SectionLevelTutorialListing.ascx Benutzersteuerelements zu (Klicken Sie hier, umDefault.aspx das Bild in voller Größe anzuzeigen)

Fügen Sie schließlich diese Seiten als Einträge zur Web.sitemap Datei hinzu. Fügen Sie insbesondere das folgende Markup nach dem Abschnitt 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.sitemapeinen Moment Zeit, um die Tutorials-Website über einen Browser anzuzeigen. Das Menü auf der linken Seite enthält nun Elemente für die Tutorials für erweiterte DAL-Szenarien.

Die Websiteübersicht enthält jetzt Einträge für die Tutorials für erweiterte DAL-Szenarien.

Abbildung 3: Die Websiteübersicht enthält jetzt Einträge für die Tutorials für erweiterte DAL-Szenarien

Schritt 2: Konfigurieren eines TableAdapter 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 typisiertes DataSet im ~/App_Code/DAL Ordner namens NorthwindWithSprocs.xsd. Da wir diesen Prozess in den vorherigen Tutorials ausführlich durchlaufen haben, werden wir die hier beschriebenen Schritte schnell durchlaufen. Wenn Sie beim Erstellen und Konfigurieren eines typisierten DataSets nicht weiterkommen oder weitere Schritt-für-Schritt-Anweisungen benötigen, lesen Sie das Tutorial Erstellen einer Datenzugriffsebene .

Fügen Sie dem Projekt ein neues DataSet hinzu, indem Sie mit der rechten Maustaste auf den DAL Ordner klicken, Neues Element hinzufügen und die DataSet-Vorlage auswählen, wie in Abbildung 4 dargestellt.

Hinzufügen eines neuen typisierten DataSets zum Projekt mit dem Namen NorthwindWithSprocs.xsd

Abbildung 4: Hinzufügen eines neuen typisierten DataSets zum Projekt namens NorthwindWithSprocs.xsd (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Dadurch wird das neue typisierte DataSet erstellt, dessen Designer geöffnet, ein neues TableAdapter erstellt und der TableAdapter-Konfigurations-Assistent gestartet. Im ersten Schritt des TableAdapter-Konfigurations-Assistenten werden wir aufgefordert, die Datenbank auszuwählen, mit der gearbeitet werden soll. Die Verbindungszeichenfolge zur Northwind-Datenbank sollte in der Dropdownliste aufgeführt werden. Wählen Sie diese Option aus, und klicken Sie auf Weiter.

Auf diesem nächsten Bildschirm können Sie auswählen, wie der TableAdapter auf die Datenbank zugreifen soll. In den vorherigen Tutorials haben wir die erste Option " SQL-Anweisungen verwenden" ausgewählt. Wählen Sie für dieses Tutorial die zweite Option, Neue gespeicherte Prozeduren erstellen aus, und klicken Sie auf Weiter.

Weisen Sie den TableAdapter an, neue gespeicherte Prozeduren zu erstellen.

Abbildung 5: Anweisen des TableAdapters, 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-Standard-Abfrage 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

Geben Sie die SELECT-Abfrage ein.

Abbildung 6: Eingeben der SELECT Abfrage (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Hinweis

Die obige Abfrage unterscheidet sich geringfügig von der Standard Abfrage von im ProductsTableAdapterNorthwind typisierten DataSet. Erinnern Sie sich daran, dass die ProductsTableAdapter im Northwind typisierten DataSet zwei korrelierte Unterabfragen enthält, um den Kategorienamen und den Firmennamen für jede Produktkategorie und jeden Lieferanten zurückzugeben. Im bevorstehenden Tutorial Aktualisieren des TableAdapters für die Verwendung von JOINs sehen wir uns das Hinzufügen dieser zugehörigen Daten zu diesem TableAdapter an.

Nehmen Sie sich einen Moment Zeit, um auf die Schaltfläche Erweiterte Optionen zu klicken. Hier können wir angeben, ob der Assistent auch Insert-, Update- und Delete-Anweisungen 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 Insert-, Update- und Delete-Anweisungen generieren ist standardmäßig aktiviert. Lassen Sie es aktiviert. Lassen Sie für dieses Tutorial die Optionen 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 gespeicherten Prozeduren zum Einfügen und Aktualisieren den gerade eingefügten oder gerade aktualisierten Datensatz ab, wie wir in Schritt 3 sehen werden.

Lassen Sie die Option Einfügen, Aktualisieren und Löschen der Anweisungen generieren aktiviert.

Abbildung 7: Lassen Sie die Option Insert-, Update- und Delete-Anweisungen generieren aktiviert.

Hinweis

Wenn die Option Optimistische Parallelität verwenden aktiviert ist, fügt der Assistent der Klausel zusätzliche Bedingungen hinzu, die WHERE verhindern, dass Daten aktualisiert werden, wenn Änderungen in anderen Feldern vorgenommen wurden. Weitere Informationen zur Verwendung des integrierten Features für die Steuerung der optimistischen Parallelität von TableAdapter finden Sie im Tutorial Implementieren optimistischer Parallelität.

Nachdem Sie die SELECT Abfrage eingegeben und bestätigt haben, dass die Option Insert-, Update- und Delete-Anweisungen generieren aktiviert ist, klicken Sie auf Weiter. Dieser nächste Bildschirm in Abbildung 8 fordert die Namen der gespeicherten Prozeduren ein, 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_Updateund Products_Delete.

Umbenennen der gespeicherten Prozeduren

Abbildung 8: Umbenennen der gespeicherten Prozeduren (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Um die T-SQL anzuzeigen, die der TableAdapter-Assistent zum Erstellen der vier gespeicherten Prozeduren verwendet, klicken Sie auf die Schaltfläche Vorschau von SQL-Skript. Im Dialogfeld Vorschau des SQL-Skripts können Sie das Skript in einer Datei speichern oder in die Zwischenablage kopieren.

Vorschau des SQL-Skripts zum Generieren der gespeicherten Prozeduren

Abbildung 9: Vorschau des SQL-Skripts, das zum Generieren der gespeicherten Prozeduren verwendet wird

Klicken Sie nach dem Benennen der gespeicherten Prozeduren auf Weiter, um die entsprechenden TableAdapter-Methoden zu benennen. Genau wie bei der Verwendung von Ad-hoc-SQL-Anweisungen können wir Methoden erstellen, die eine vorhandene DataTable füllen oder eine neue zurückgeben. Wir können auch angeben, ob der TableAdapter das DB-Direct-Muster zum Einfügen, Aktualisieren und Löschen von Datensätzen enthalten soll. Lassen Sie alle drei Kontrollkästchen aktiviert, aber benennen Sie die Return a DataTable-Methode in GetProducts um (wie in Abbildung 10 dargestellt).

Nennen Sie die Methoden Fill und GetProducts.

Abbildung 10: Benennen Sie die Methoden Fill und GetProducts (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Klicken Sie auf Weiter, um eine Zusammenfassung der Vom Assistenten ausgeführten Schritte anzuzeigen. Schließen Sie den Assistenten ab, indem Sie auf die Schaltfläche Fertig stellen klicken. Sobald der Assistent abgeschlossen ist, werden Sie zum DataSet-Designer zurückgegeben, der nun das ProductsDataTableenthalten sollte.

Der DataSet-Designer zeigt die neu hinzugefügten ProductsDataTable an.

Abbildung 11: Die dataSet-Designer zeigt das neu hinzugefügte ProductsDataTable Bild an (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Schritt 3: Untersuchen der neu erstellten gespeicherten Prozeduren

Der in Schritt 2 verwendete TableAdapter-Assistent hat automatisch die gespeicherten Prozeduren zum Auswählen, Einfügen, Aktualisieren und Löschen von Daten erstellt. 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 durchführen. Wie Abbildung 12 zeigt, enthält die Northwind-Datenbank vier neue gespeicherte Prozeduren: Products_Delete, Products_Insert, Products_Selectund Products_Update.

Die vier in Schritt 2 erstellten gespeicherten Prozeduren befinden sich im Ordner gespeicherte Prozeduren der Datenbank.

Abbildung 12: Die vier in Schritt 2 erstellten gespeicherten Prozeduren befinden sich 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, versuchen Sie, mit der rechten Maustaste auf den Ordner Gespeicherte Prozeduren zu klicken und Aktualisieren auszuwählen.

Um eine gespeicherte Prozedur anzuzeigen oder zu ändern, doppelklicken Sie auf ihren Namen im server-Explorer, 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.

Gespeicherte Prozeduren können in Visual Studio geöffnet und geändert werden.

Abbildung 13: Gespeicherte Prozeduren können in Visual Studio geöffnet und geändert werden (Klicken Sie, um das bild in voller Größe anzuzeigen)

Die Inhalte der gespeicherten Products_Delete Prozeduren und Products_Select der gespeicherten Prozeduren sind recht einfach. Die Products_Insert gespeicherten Prozeduren und Products_Update die gespeicherten Prozeduren hingegen erfordern eine genauere Überprüfung, da beide eine SELECT Anweisung nach ihren INSERT Und UPDATE -Anweisungen ausführen. Die gespeicherte Prozedur besteht beispielsweise aus der Products_Insert folgenden SQL:

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 Products Spalten, die von der SELECT im TableAdapter-Assistenten angegebenen Abfrage zurückgegeben wurden, und diese Werte werden in einer INSERT Anweisung verwendet. Nach der INSERT -Anweisung wird eine SELECT Abfrage verwendet, um die Products Spaltenwerte (einschließlich ) ProductIDdes neu hinzugefügten Datensatzes zurückzugeben. Diese Aktualisierungsfunktion ist nützlich, wenn Sie einen neuen Datensatz mithilfe des Batchupdatemusters hinzufügen, da die neu hinzugefügten ProductRowProductID Instanzeigenschaften automatisch mit den automatisch inkrementierten Werten aktualisiert werden, die von der Datenbank zugewiesen werden.

Der folgende Code veranschaulicht dieses Feature. Es enthält ein ProductsTableAdapter und ProductsDataTable erstellt für das NorthwindWithSprocs typisierte DataSet. Ein neues Produkt wird der Datenbank hinzugefügt, indem ein ProductsRow instance erstellt, dessen Werte angegeben und die TableAdapter-Methode Update aufgerufen wird, wobei übergeben wirdProductsDataTable. Intern zählt die TableAdapter-Methode Update die Instanzen in der ProductsRow übergebenen DataTable auf (in diesem Beispiel gibt es nur eine - die soeben hinzugefügte ) und führt den entsprechenden Einfüge-, Update- 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. Anschließend ProductsRow wird der Wert instance s ProductID aktualisiert. Nachdem die Update -Methode abgeschlossen ist, können wir über die s-Eigenschaft ProductID auf den neu hinzugefügten ProductsRow Wert des Datensatzes ProductID 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 auch 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 ProductIDenthält: @Original_ProductID und @ProductID. Diese Funktionalität ermöglicht Szenarien, in denen der Primärschlüssel geändert werden kann. In einer Mitarbeiterdatenbank kann beispielsweise jeder Mitarbeiterdatensatz die Sozialversicherungsnummer des Mitarbeiters als Primärschlüssel verwenden. Um die Sozialversicherungsnummer eines bestehenden Arbeitnehmers zu ändern, muss sowohl die neue Sozialversicherungsnummer als auch die ursprüngliche angegeben werden. Für die Products Tabelle ist diese Funktionalität nicht erforderlich, da die ProductID Spalte eine IDENTITY Spalte ist und nie geändert werden sollte. Tatsächlich enthält die UPDATE -Anweisung in der Products_Update gespeicherten Prozedur die Spalte nicht in ihrer ProductID Spaltenliste. @Original_ProductID Während sie also in der UPDATE Anweisung s-Klausel WHERE verwendet wird, ist sie 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-Methoden aktualisiert werden, die diese gespeicherte Prozedur verwenden.

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 Products_Update gespeicherte Prozedur, löschen Sie den @Original_ProductID Parameter, und ändern Sie in der WHERE -Klausel der UPDATE -Anweisung den verwendeten Parameternamen in @Original_ProductID@ProductID. Nach diesen Änderungen sollte die T-SQL-Datei in 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)

Um diese Änderungen in der Datenbank zu speichern, klicken Sie auf der Symbolleiste auf das Symbol Speichern, oder drücken Sie STRG+S. An diesem Punkt erwartet @Original_ProductID die Products_Update gespeicherte Prozedur keinen Eingabeparameter, aber der TableAdapter ist so konfiguriert, dass ein solcher Parameter übergeben wird. Sie können die Parameter anzeigen, die der TableAdapter an die Products_Update gespeicherte Prozedur sendet, indem Sie den TableAdapter im DataSet-Designer auswählen, zum Eigenschaftenfenster wechseln und auf die Auslassungspunkte in der UpdateCommand Sammlung s Parameters klicken. Dadurch wird das Dialogfeld Parameters Collection Editor in Abbildung 14 angezeigt.

Die Parameters-Auflistung Editor Listen die verwendeten Parameter, die an die gespeicherte Products_Update Prozedur übergeben werden

Abbildung 14: Die Parameters-Auflistung Editor Listen die an die Products_Update gespeicherte Prozedur übergebenen Parameter

Sie können diesen Parameter von hier entfernen, indem Sie einfach den @Original_ProductID Parameter aus der Liste der Elemente auswählen und auf die Schaltfläche Entfernen klicken.

Alternativ können Sie die für alle Methoden verwendeten Parameter aktualisieren, indem Sie mit der rechten Maustaste auf den TableAdapter im Designer klicken und Konfigurieren auswählen. Dadurch wird der TableAdapter-Konfigurations-Assistent geöffnet, der die gespeicherten Prozeduren auflistet, die zum Auswählen, Einfügen, Aktualisieren und Löschen verwendet werden, sowie die Parameter, die die gespeicherten Prozeduren empfangen sollen. Wenn Sie auf die Dropdownliste Update klicken, werden die erwarteten Eingabeparameter für gespeicherte Products_Update Prozeduren angezeigt, die jetzt nicht mehr enthalten @Original_ProductID sind (siehe Abbildung 15). Klicken Sie einfach auf Fertig stellen, um die vom TableAdapter verwendete Parameterauflistung automatisch zu aktualisieren.

Alternativ können Sie den Konfigurations-Assistenten für TableAdapter verwenden, um die Methodenparametersammlungen zu aktualisieren.

Abbildung 15: Alternativ können Sie den Konfigurations-Assistenten für TableAdapter verwenden, um die Methodenparametersammlungen zu aktualisieren (klicken, um das vollständige Bild anzuzeigen)

Schritt 5: Hinzufügen zusätzlicher TableAdapter-Methoden

Wie Schritt 2 veranschaulicht, ist es beim Erstellen eines neuen TableAdapters einfach, die entsprechenden gespeicherten Prozeduren automatisch zu generieren. Das gleiche gilt für das Hinzufügen zusätzlicher Methoden zu einem TableAdapter. Um dies zu veranschaulichen, fügen wir der ProductsTableAdapter in Schritt 2 erstellten Methode eine GetProductByProductID(productID) Methode hinzu. Diese Methode verwendet als Eingabe einen ProductID Wert und gibt Details zum angegebenen Produkt zurück.

Klicken Sie zunächst mit der rechten Maustaste auf den TableAdapter, und wählen Sie im Kontextmenü Abfrage hinzufügen aus.

Hinzufügen einer neuen Abfrage zum TableAdapter

Abbildung 16: Hinzufügen einer neuen Abfrage zum TableAdapter

Dadurch wird der TableAdapter-Abfragekonfigurations-Assistent gestartet, der zuerst aufgefordert wird, 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.

Wählen Sie die Option Neue gespeicherte Prozedur erstellen aus.

Abbildung 17: Wählen Sie die Option Neue gespeicherte Prozedur erstellen aus (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Auf dem nächsten Bildschirm werden wir aufgefordert, den Typ der auszuführenden Abfrage zu identifizieren, unabhängig davon, ob eine Reihe von Zeilen oder einen einzelnen skalaren Wert zurückgegeben oder eine UPDATE- oder INSERTDELETE -Anweisung ausgeführt wird. Da die GetProductByProductID(productID) Methode eine Zeile zurückgibt, lassen Sie die Option SELECT, die Zeilen zurückgibt, ausgewählt, und klicken Sie auf Weiter.

Wählen Sie die Option SELECT aus, die Zeilen zurückgibt.

Abbildung 18: Wählen Sie die Option SELECT aus, die Zeilen zurückgibt (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Auf dem nächsten Bildschirm wird die TableAdapter-Standard Abfrage angezeigt, die nur den Namen der gespeicherten Prozedur () auflistetdbo.Products_Select. 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

Ersetzen Sie den Namen der gespeicherten Prozedur durch eine SELECT-Abfrage.

Abbildung 19: Ersetzen Sie den Namen der gespeicherten Prozedur durch eine SELECT Abfrage (Klicken Sie, um das bild in voller Größe anzuzeigen)

Auf dem 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.

Benennen Sie die neue gespeicherte Prozedur Products_SelectByProductID

Abbildung 20: Name 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 Füllen einer DataTable, Rückgabe eines DataTable-Musters oder beides verwendet werden soll. Lassen Sie für diese Methode beide Optionen aktiviert, benennen Sie die Methoden jedoch in und GetProductByProductIDumFillByProductID. Klicken Sie auf Weiter, um eine Zusammenfassung der Vom Assistenten ausgeführten Schritte anzuzeigen, und klicken Sie dann auf Fertig stellen, um den Assistenten abzuschließen.

Benennen Sie die TableAdapter-Methoden in FillByProductID und GetProductByProductID um.

Abbildung 21: Umbenennen der TableAdapter-Methoden in FillByProductID und GetProductByProductID (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Nach Abschluss des Assistenten steht dem TableAdapter eine neue Methode zur Verfügung, GetProductByProductID(productID) die beim Aufrufen die Products_SelectByProductID soeben erstellte gespeicherte Prozedur ausführt. Nehmen Sie sich einen Moment Zeit, um diese neue gespeicherte Prozedur auf dem Server Explorer anzuzeigen, indem Sie in den Ordner Gespeicherte Prozeduren bohren 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 die SelectByProductID gespeicherte Prozedur als Eingabeparameter verwendet @ProductID und die SELECT Anweisung 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

Während der gesamten Tutorialreihe haben wir uns bemüht, eine mehrschichtige Architektur beizubehalten, in der die Präsentationsebene alle Aufrufe an die Geschäftslogikebene (Business Logic Layer, BLL) vorgenommen hat. Um diese Entwurfsentscheidung einzuhalten, müssen wir zunächst eine BLL-Klasse für das neue typisierte DataSet erstellen, bevor wir von der Präsentationsebene auf Produktdaten zugreifen können.

Erstellen Sie eine neue Klassendatei namens ProductsBLLWithSprocs.vb im ~/App_Code/BLL Ordner, und fügen Sie ihr den 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 Tutorials, verwendet aber die ProductsTableAdapter -Objekte und ProductsDataTable aus dem NorthwindWithSprocs DataSet. Anstatt beispielsweise eine -Anweisung am Anfang der Klassendatei zu verwenden Imports NorthwindTableAdapters , verwendet ProductsBLL die ProductsBLLWithSprocs -Klasse Imports NorthwindWithSprocsTableAdapters. Ebenso werden die ProductsDataTable in dieser Klasse verwendeten Objekte und ProductsRow mit dem NorthwindWithSprocs Namespace präfixiert. Die ProductsBLLWithSprocs -Klasse bietet zwei Datenzugriffsmethoden GetProducts und GetProductByProductID- und -Methoden zum Hinzufügen, Aktualisieren und Löschen eines einzelnen Produkts instance.

Schritt 7: Arbeiten mit demNorthwindWithSprocsDataSet über die Präsentationsebene

An diesem Punkt haben wir eine DAL erstellt, die gespeicherte Prozeduren verwendet, um auf die zugrunde liegenden Datenbankdaten zuzugreifen und diese zu ändern. Wir haben auch eine rudimentäre BLL mit Methoden zum Abrufen aller Produkte oder eines bestimmten Produkts sowie Methoden zum Hinzufügen, Aktualisieren und Löschen von Produkten erstellt. Um dieses Tutorial abzurunden, 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 die Designer, und nennen Sie sie Products. Wählen Sie im Smarttag des GridView-Tags aus, um es an eine neue ObjectDataSource mit dem Namen ProductsDataSourcezu binden. Konfigurieren Sie objectDataSource für die Verwendung der ProductsBLLWithSprocs -Klasse, wie in Abbildung 22 gezeigt.

Konfigurieren der ObjectDataSource für die Verwendung der ProductsBLLWithSprocs-Klasse

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 enthält zwei Optionen: GetProductsGetProductByProductID. Da alle Produkte in gridView angezeigt werden sollen, wählen Sie die GetProducts -Methode aus. Die Dropdownlisten in den Registerkarten UPDATE, INSERT und DELETE verfügen jeweils nur über eine Methode. Stellen Sie sicher, dass für jede dieser Dropdownlisten die entsprechende Methode ausgewählt ist, und klicken Sie dann auf Fertig stellen.

Nachdem der ObjectDataSource-Assistent abgeschlossen ist, fügt Visual Studio BoundFields und ein CheckBoxField-Element zur GridView für die Produktdatenfelder hinzu. Aktivieren Sie die integrierten Bearbeitungs- und Löschfunktionen von GridView, indem Sie die Optionen Bearbeiten aktivieren und Löschen aktivieren aktivieren, die im Smarttag vorhanden sind.

Die Seite enthält eine GridView mit aktivierter Bearbeitungs- und Löschungsunterstützung

Abbildung 23: Die Seite enthält eine GridView mit aktivierter Bearbeitungs- und Löschungsunterstützung (Klicken, um das bild in voller Größe anzuzeigen)

Wie in den vorherigen Tutorials erläutert, legt Visual Studio nach Abschluss des ObjectDataSource-Assistenten die OldValuesParameterFormatString Eigenschaft auf original_{0} fest. Dies muss auf den Standardwert von {0} zurückgesetzt werden, damit die Datenänderungsfeatures ordnungsgemäß funktionieren, wenn die Von den Methoden in unserer BLL erwarteten Parameter ordnungsgemäß funktionieren. Achten Sie daher darauf, die OldValuesParameterFormatString Eigenschaft auf {0} festzulegen, oder entfernen Sie die Eigenschaft vollständig aus der deklarativen Syntax.

Nach Abschluss des Assistenten Datenquelle konfigurieren, die Bearbeitungs- und Löschunterstützung in GridView aktiviert und die ObjectDataSource-Eigenschaft OldValuesParameterFormatString auf den Standardwert zurückgegeben wurde, 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 bereinigen, indem wir die Bearbeitungsschnittstelle so anpassen, dass die Überprüfung eingeschlossen wird, dass die CategoryID Spalten und SupplierID als DropDownLists gerendert werden usw. Wir könnten auch eine clientseitige Bestätigung zur Schaltfläche Löschen hinzufügen, und ich ermutige Sie, sich die Zeit zu nehmen, diese Verbesserungen zu implementieren. Da diese Themen jedoch in früheren Tutorials behandelt wurden, werden wir sie hier nicht erneut behandeln.

Unabhängig davon, ob Sie GridView verbessern oder nicht, testen Sie die Kernfunktionen der Seite in einem Browser. Wie Abbildung 24 zeigt, listet die Seite die Produkte in einer GridView auf, die Funktionen zum Bearbeiten und Löschen pro Zeile bietet.

Die Produkte können in der GridView angezeigt, bearbeitet und gelöscht werden.

Abbildung 24: Die Produkte können aus der GridView angezeigt, bearbeitet und gelöscht werden (klicken, um das bild in voller Größe anzuzeigen)

Zusammenfassung

Die TableAdapters in einem typisierten DataSet können mithilfe von Ad-hoc-SQL-Anweisungen oder über gespeicherte Prozeduren auf Daten aus der Datenbank zugreifen. Beim Arbeiten mit gespeicherten Prozeduren können entweder vorhandene gespeicherte Prozeduren verwendet werden, oder der TableAdapter-Assistent kann angewiesen werden, neue gespeicherte Prozeduren basierend auf einer SELECT Abfrage zu erstellen. In diesem Tutorial haben wir untersucht, wie die gespeicherten Prozeduren automatisch für uns erstellt werden.

Während die automatisch generierten gespeicherten Prozeduren Zeit sparen, gibt es einige Fälle, in denen die vom Assistenten erstellte gespeicherte Prozedur nicht mit dem übereinstimmt, was wir selbst erstellt hätten. Ein Beispiel ist die Products_Update gespeicherte Prozedur, die sowohl eingabeparameter als auch @Original_ProductID@ProductID eingabeparameter 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 ein feines Maß an Kontrolle über die Befehle der gespeicherten Prozedur zu erhalten. In beiden Fällen möchten wir den TableAdapter anweisen, vorhandene gespeicherte Prozeduren für seine Methoden zu verwenden. Wie Sie dies erreichen, erfahren Sie im nächsten Tutorial.

Viel Spaß beim Programmieren!

Weitere Informationen

Weitere Informationen zu den in diesem Tutorial erläuterten Themen finden Sie in den folgenden Ressourcen:

Zum Autor

Scott Mitchell, Autor von sieben ASP/ASP.NET-Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.

Besonderen Dank an

Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Lead Reviewer für dieses Tutorial war Hilton Geisenow. Möchten Sie meine anstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.