Freigeben über


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

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. Auf diesem nächsten Bildschirm in Abbildung 8 werden die Namen der gespeicherten Prozeduren angegeben, die vom Assistenten zum Auswählen, Einfügen, Aktualisieren und Löschen von Daten erstellt werden. Ä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 vom TableAdapter-Assistenten zum Erstellen der vier gespeicherten Prozeduren verwendet wird, klicken Sie auf die Schaltfläche Sql-Skriptvorschau. 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 zum Generieren der gespeicherten Prozeduren

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, benennen Sie die Methode DataTable zurückgeben in GetProducts um (wie in Abbildung 10 dargestellt).

Benennen 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 Schritte anzuzeigen, die der Assistent ausführt. 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 jetzt enthalten ProductsDataTablesollte.

Die dataSet-Designer zeigt die neu hinzugefügte ProductsDataTable an.

Abbildung 11: DataSets Designer Zeigt das neu hinzugefügte ProductsDataTableBild (Klicken Sie hier, 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 ausfü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 gespeicherten Prozeduren, die in Schritt 2 erstellt wurden, finden Sie im Ordner gespeicherte Prozeduren der Datenbank.

Hinweis

Wenn die Server-Explorer nicht angezeigt wird, wechseln Sie zum Menü Ansicht, und wählen Sie die Option Server Explorer aus. Wenn die produktbezogenen gespeicherten Prozeduren aus Schritt 2 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 den Namen des Explorer Server, 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, wenn sie geöffnet wird.

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 hier, um ein Bild in voller Größe anzuzeigen)

Der Inhalt der gespeicherten Prozedur und Products_Select der Products_Delete gespeicherten Prozedur ist recht einfach. Die Products_Insert gespeicherten Prozeduren und Products_Update erfordern dagegen eine genauere Prüfung, da beide eine SELECT Anweisung nach ihren INSERT - und UPDATE -Anweisungen ausführen. Die gespeicherte Prozedur besteht beispielsweise aus dem Products_Insert folgenden SQL-Code:

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 beim Hinzufügen eines neuen Datensatzes mithilfe des Batchupdatemusters nützlich, 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 eine 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 ProductsDataTablewird. Intern listet 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 Befehl zum Einfügen, Aktualisieren oder Löschen 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 ProductsRow Wert instance s ProductID wird dann aktualisiert. Nachdem die Update -Methode abgeschlossen wurde, können wir über die s-Eigenschaft ProductID auf den ProductsRow neu hinzugefügten Datensatzwert zugreifenProductID.

// Create the ProductsTableAdapter and ProductsDataTable
NorthwindWithSprocsTableAdapters.ProductsTableAdapter productsAPI = 
    new NorthwindWithSprocsTableAdapters.ProductsTableAdapter();
NorthwindWithSprocs.ProductsDataTable products = 
    new NorthwindWithSprocs.ProductsDataTable();
// Create a new ProductsRow instance and set its properties
NorthwindWithSprocs.ProductsRow product = 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
int newlyAddedProductIDValue = product.ProductID;

Die Products_Update gespeicherte Prozedur schließt auf ähnliche Weise eine -Anweisung nach ihrer UPDATE -Anweisung einSELECT.

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 möglicherweise geändert wird. In einer Mitarbeiterdatenbank kann beispielsweise jeder Mitarbeiterdatensatz 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 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 der ProductID Spaltenliste. @Original_ProductID Während 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 die TableAdapter-Methoden, die diese gespeicherte Prozedur verwenden, ebenfalls aktualisiert werden.

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 von in @Original_ProductID@ProductID. Nachdem Sie diese Änderungen vorgenommen haben, 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 für die Übergabe eines solchen Parameters konfiguriert. Sie können die Parameter anzeigen, die der TableAdapter an die Products_Update gespeicherte Prozedur sendet, indem Sie im DataSet-Designer den TableAdapter 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 an die Products_Update gespeicherten Prozedur übergebenen Parameter.

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 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 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, zusammen mit den Parametern, die die gespeicherten Prozeduren erhalten 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 seine Methoden-Parameterauflistungen zu aktualisieren.

Abbildung 15: Alternativ können Sie den Konfigurations-Assistenten für TableAdapter verwenden, um seine 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 TableAdapters einfach, die entsprechenden gespeicherten Prozeduren automatisch zu generieren. Dasselbe gilt für das Hinzufügen zusätzlicher Methoden zu einem TableAdapter. Um dies zu veranschaulichen, fügen wir dem ProductsTableAdapter in Schritt 2 erstellten 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 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: Auswählen der Option "Neue gespeicherte Prozedur erstellen" (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 ein einzelner Skalarwert zurückgegeben oder eine - oder INSERT- oder DELETE -UPDATEAnweisung ausgeführt wird. Da die GetProductByProductID(productID) -Methode eine Zeile zurückgibt, lassen Sie die Option SELECT, die die Zeile zurückgibt, ausgewählt, und klicken Sie auf Weiter.

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

Abbildung 18: Wählen Sie die OPTION SELECT aus, die die Zeilenoption zurückgibt (Klicken Sie hier, 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 (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

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

Abbildung 19: Ersetzen des Namens der gespeicherten Prozedur durch eine SELECT Abfrage (Klicken Sie hier, 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: 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 Ausfü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 Schritte anzuzeigen, die der Assistent ausführt, 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 bei Aufruf die Products_SelectByProductID soeben erstellte gespeicherte Prozedur ausführt. Nehmen Sie sich einen Moment Zeit, um diese neue gespeicherte Prozedur aus dem Server Explorer anzuzeigen, indem Sie einen Drill in den Ordner Gespeicherte Prozeduren einfügen 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 akzeptiert @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.cs im ~/App_Code/BLL Ordner, und fügen Sie ihr den folgenden Code hinzu:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindWithSprocsTableAdapters;
[System.ComponentModel.DataObject]
public class ProductsBLLWithSprocs
{
    private ProductsTableAdapter _productsAdapter = null;
    protected ProductsTableAdapter Adapter
    {
        get
        {
            if (_productsAdapter == null)
                _productsAdapter = new ProductsTableAdapter();
            return _productsAdapter;
        }
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Select, true)]
    public NorthwindWithSprocs.ProductsDataTable GetProducts()
    {
        return Adapter.GetProducts();
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Select, false)]
    public NorthwindWithSprocs.ProductsDataTable GetProductByProductID(int productID)
    {
        return Adapter.GetProductByProductID(productID);
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Insert, true)]
    public bool AddProduct
        (string productName, int? supplierID, int? categoryID, 
         string quantityPerUnit, decimal? unitPrice, short? unitsInStock, 
         short? unitsOnOrder, short? reorderLevel, bool discontinued)
    {
        // Create a new ProductRow instance
        NorthwindWithSprocs.ProductsDataTable products = 
            new NorthwindWithSprocs.ProductsDataTable();
        NorthwindWithSprocs.ProductsRow product = products.NewProductsRow();
        product.ProductName = productName;
        if (supplierID == null) 
            product.SetSupplierIDNull(); 
        else 
            product.SupplierID = supplierID.Value;
        if (categoryID == null) 
            product.SetCategoryIDNull(); 
        else 
            product.CategoryID = categoryID.Value;
        if (quantityPerUnit == null) 
            product.SetQuantityPerUnitNull(); 
        else 
            product.QuantityPerUnit = quantityPerUnit;
        if (unitPrice == null) 
            product.SetUnitPriceNull(); 
        else 
            product.UnitPrice = unitPrice.Value;
        if (unitsInStock == null) 
            product.SetUnitsInStockNull(); 
        else 
            product.UnitsInStock = unitsInStock.Value;
        if (unitsOnOrder == null) 
            product.SetUnitsOnOrderNull(); 
        else 
            product.UnitsOnOrder = unitsOnOrder.Value;
        if (reorderLevel == null)
            product.SetReorderLevelNull(); 
        else 
            product.ReorderLevel = reorderLevel.Value;
        product.Discontinued = discontinued;
        // Add the new product
        products.AddProductsRow(product);
        int rowsAffected = Adapter.Update(products);
        // Return true if precisely one row was inserted, otherwise false
        return rowsAffected == 1;
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Update, true)]
    public bool UpdateProduct
        (string productName, int? supplierID, int? categoryID, string quantityPerUnit,
        decimal? unitPrice, short? unitsInStock, short? unitsOnOrder, 
        short? reorderLevel, bool discontinued, int productID)
    {
        NorthwindWithSprocs.ProductsDataTable products = 
            Adapter.GetProductByProductID(productID);
        if (products.Count == 0)
            // no matching record found, return false
            return false;
        NorthwindWithSprocs.ProductsRow product = products[0];
        product.ProductName = productName;
        if (supplierID == null) 
            product.SetSupplierIDNull(); 
        else 
            product.SupplierID = supplierID.Value;
        if (categoryID == null) 
            product.SetCategoryIDNull(); 
        else 
            product.CategoryID = categoryID.Value;
        if (quantityPerUnit == null) 
            product.SetQuantityPerUnitNull(); 
        else 
            product.QuantityPerUnit = quantityPerUnit;
        if (unitPrice == null) 
            product.SetUnitPriceNull(); 
        else 
            product.UnitPrice = unitPrice.Value;
        if (unitsInStock == null) 
            product.SetUnitsInStockNull(); 
        else 
            product.UnitsInStock = unitsInStock.Value;
        if (unitsOnOrder == null) 
            product.SetUnitsOnOrderNull(); 
        else 
            product.UnitsOnOrder = unitsOnOrder.Value;
        if (reorderLevel == null) 
            product.SetReorderLevelNull(); 
        else 
            product.ReorderLevel = reorderLevel.Value;
        product.Discontinued = discontinued;
        // Update the product record
        int rowsAffected = Adapter.Update(product);
        // Return true if precisely one row was updated, otherwise false
        return rowsAffected == 1;
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Delete, true)]
    public bool DeleteProduct(int productID)
    {
        int rowsAffected = Adapter.Delete(productID);
        // Return true if precisely one row was deleted, otherwise false
        return rowsAffected == 1;
    }
}

Diese Klasse imitiert die ProductsBLL Klassensemantik aus früheren Tutorials, verwendet jedoch die ProductsTableAdapter -Objekte und ProductsDataTable aus dem NorthwindWithSprocs DataSet. Anstatt beispielsweise eine using NorthwindTableAdapters -Anweisung am Anfang der Klassendatei zu haben, verwendet ProductsBLLusing NorthwindWithSprocsTableAdaptersdie ProductsBLLWithSprocs -Klasse . Ebenso wird den - und ProductsRow -Objekten, die ProductsDataTable in dieser Klasse verwendet werden, der NorthwindWithSprocs -Namespace vorangestellt. Die ProductsBLLWithSprocs -Klasse stellt zwei Datenzugriffsmethoden bereit, GetProducts und GetProductByProductIDmethoden zum Hinzufügen, Aktualisieren und Löschen eines einzelnen Produkts instance.

Schritt 7: Arbeiten mit demNorthwindWithSprocsDataSet auf der 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 zusammen mit 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 ein GridView-Objekt aus der Toolbox auf die Designer, und nennen Sie sie Products. Wählen Sie im Smarttag von GridView 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 dargestellt.

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 verfügt über zwei Optionen: GetProducts und GetProductByProductID. Da alle Produkte in GridView angezeigt werden sollen, wählen Sie die GetProducts -Methode aus. Die Dropdownlisten auf 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 im Smarttag aktivieren.

Die Seite enthält ein GridView-Objekt mit aktivierter Bearbeitungs- und Löschunterstützung.

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

Wie in den vorherigen Tutorials beschrieben, 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 unter Berücksichtigung der parameter ordnungsgemäß funktionieren, die von den Methoden in unserer BLL erwartet werden. Achten Sie daher darauf, die OldValuesParameterFormatString Eigenschaft auf {0} festzulegen, oder entfernen Sie die Eigenschaft vollständig aus der deklarativen Syntax.

Nachdem Sie den Assistenten zum Konfigurieren von Datenquellen abgeschlossen, die Bearbeitungs- und Löschunterstützung in GridView aktiviert und die ObjectDataSource-Eigenschaft OldValuesParameterFormatString auf den Standardwert zurückgegeben haben, 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 Bearbeitungsoberfläche so anpassen, dass sie die Überprüfung enthält, 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 ermuntere Sie, sich die Zeit zu nehmen, um diese Verbesserungen zu implementieren. Da diese Themen jedoch in den vorherigen 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, werden auf der Seite die Produkte in einer GridView aufgeführt, die Funktionen zum Bearbeiten und Löschen pro Zeile bietet.

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

Abbildung 24: Die Produkte können in GridView angezeigt, bearbeitet und gelöscht werden (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Zusammenfassung

Die TableAdapters in einem typisierten DataSet können mithilfe von SQL-Ad-hoc-Anweisungen oder über gespeicherte Prozeduren auf Daten aus der Datenbank zugreifen. Bei der Arbeit 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.

Obwohl die automatisch generierten gespeicherten Prozeduren Zeit sparen, gibt es 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 die @ProductID Eingabeparameter als auch @Original_ProductID die 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 behandelten 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 Hours. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.

Besonderer 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 bevorstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.