Freigeben über


Verwenden von parametrisierten Abfragen mit der SqlDataSource-Komponente (C#)

von Scott Mitchell

PDF herunterladen

In diesem Tutorial setzen wir unsere Betrachtung des SqlDataSource-Controls fort und lernen, wie parametrisierte Abfragen definiert werden. Die Parameter können sowohl deklarativ als auch programmgesteuert angegeben werden und aus einer Reihe von Speicherorten wie der Abfragezeichenfolge, dem Sitzungsstatus, anderen Steuerelementen und mehr abgerufen werden.

Einleitung

Im vorherigen Lernprogramm haben wir erfahren, wie Sie das SqlDataSource-Steuerelement verwenden, um Daten direkt aus einer Datenbank abzurufen. Mithilfe des Assistenten "Datenquelle konfigurieren" können wir die Datenbank auswählen und dann entweder die Spalten auswählen, die aus einer Tabelle oder Ansicht zurückgegeben werden sollen. geben Sie eine benutzerdefinierte SQL-Anweisung ein; oder verwenden Sie eine gespeicherte Prozedur. Unabhängig davon, ob Sie Spalten aus einer Tabelle oder Ansicht auswählen oder eine benutzerdefinierte SQL-Anweisung eingeben, wird die Eigenschaft des SqlDataSource-Steuerelements SelectCommand der resultierenden Ad-hoc-SQL-Anweisung SELECT zugewiesen, und es handelt sich um diese SELECT Anweisung, die ausgeführt wird, wenn die SqlDataSource-Methode Select() aufgerufen wird (entweder programmgesteuert oder automatisch aus einem Datenwebsteuerelement).

Die SQL-Anweisungen SELECT, die in den Demos des vorherigen Tutorials verwendet wurden, fehlten WHERE-Klauseln. In einer SELECT Anweisung kann die WHERE Klausel verwendet werden, um die zurückgegebenen Ergebnisse einzuschränken. Um beispielsweise die Namen von Produkten anzuzeigen, die mehr als 50,00 $ kosten, könnten wir die folgende Abfrage verwenden:

SELECT ProductName
FROM Products
WHERE UnitPrice > 50.00

In der Regel werden die in einer WHERE Klausel verwendeten Werte von einer externen Quelle bestimmt, z. B. von einem Abfragezeichenfolgenwert, einer Sitzungsvariable oder von Benutzereingaben eines Websteuerelements auf der Seite. Im Idealfall werden solche Eingaben über die Verwendung von Parametern angegeben. In Microsoft SQL Server werden Parameter mit @parameterName angegeben, wie im Beispiel:

SELECT ProductName
FROM Products
WHERE UnitPrice > @Price

SqlDataSource unterstützt parametrisierte Abfragen, sowohl für SELECT-Anweisungen als auch für INSERT, UPDATE- und DELETE-Anweisungen. Darüber hinaus können die Parameterwerte automatisch aus einer Vielzahl von Quellen abgerufen werden, wie der Abfragezeichenfolge, dem Sitzungszustand, den Steuerelementen auf der Seite usw., oder sie können programmgesteuert zugewiesen werden. In diesem Lernprogramm wird erläutert, wie parametrisierte Abfragen definiert werden und wie sie die Parameterwerte sowohl deklarativ als auch programmgesteuert angeben.

Hinweis

Im vorherigen Lernprogramm haben wir die ObjectDataSource verglichen, die unser Wahltool für die ersten 46 Lernprogramme mit der SqlDataSource war, wobei sie ihre konzeptionellen Ähnlichkeiten notiert. Diese Ähnlichkeiten erstrecken sich auch auf Parameter. Die Parameter von ObjectDataSource, die den Eingabeparametern der Methoden in der Geschäftslogikebene zugeordnet sind. Mit sqlDataSource werden die Parameter direkt in der SQL-Abfrage definiert. Beide Steuerelemente verfügen über Auflistungen von Parametern für ihre Select(), Insert(), Update() und Delete()-Methoden, und beide können diese Parameterwerte aus vordefinierten Quellen (Abfragezeichenfolgenwerte, Sitzungsvariablen usw.) stammen oder programmgesteuert zugewiesen werden.

Erstellen einer parametrisierten Abfrage

Der Assistent zur Konfiguration der SqlDataSource-Datenquelle bietet drei Möglichkeiten, den Befehl zu definieren, der zum Abrufen von Datenbankdatensätzen ausgeführt wird.

  • Indem Sie die Spalten aus einer vorhandenen Tabelle oder Ansicht auswählen,
  • Durch Eingabe einer benutzerdefinierten SQL-Anweisung oder
  • Durch Auswählen einer gespeicherten Prozedur

Beim Auswählen von Spalten aus einer vorhandenen Tabelle oder Ansicht müssen die Parameter für die WHERE Klausel über das Dialogfeld "Klausel hinzufügen WHERE " angegeben werden. Beim Erstellen einer benutzerdefinierten SQL-Anweisung können Sie jedoch die Parameter direkt in die WHERE-Klausel eingeben, indem Sie @parameterName verwenden, um jeden Parameter anzugeben. Eine gespeicherte Prozedur besteht aus einer oder mehreren SQL-Anweisungen, und diese Anweisungen können parametrisiert werden. Die in den SQL-Anweisungen verwendeten Parameter müssen jedoch als Eingabeparameter an die gespeicherte Prozedur übergeben werden.

Da das Erstellen einer parametrisierten Abfrage davon abhängt, wie die SqlDataSource s SelectCommand angegeben wird, werfen wir einen Blick auf alle drei Ansätze. Um zu beginnen, öffnen Sie die ParameterizedQueries.aspx Seite im SqlDataSource Ordner, ziehen Sie ein SqlDataSource-Steuerelement aus der Toolbox auf den Designer, und setzen Sie dessen ID auf Products25BucksAndUnderDataSource. Klicken Sie als Nächstes auf den Link "Datenquelle konfigurieren" aus dem Smarttag des Steuerelements. Wählen Sie die zu verwendende Datenbank (NORTHWINDConnectionString) aus, und klicken Sie auf "Weiter".

Schritt 1: Hinzufügen einer WHERE-Klausel beim Auswählen der Spalten aus einer Tabelle oder Ansicht

Wenn Sie die Daten auswählen, die mit dem SqlDataSource-Steuerelement aus der Datenbank zurückgegeben werden sollen, können wir im Assistenten zum Konfigurieren von Datenquellen einfach die Spalten auswählen, die aus einer vorhandenen Tabelle oder Ansicht zurückgegeben werden sollen (siehe Abbildung 1). Dadurch wird automatisch eine SQL-Anweisung SELECT erstellt, die an die Datenbank gesendet wird, wenn die SqlDataSource-Methode Select() aufgerufen wird. Wählen Sie wie im vorherigen Tutorial die Tabelle "Produkte" aus der Dropdown-Liste und überprüfen Sie die Spalten ProductID, ProductName und UnitPrice.

Auswählen der Spalten, die aus einer Tabelle oder Ansicht zurückgegeben werden sollen

Abbildung 1: Auswählen der spalten, die aus einer Tabelle oder Ansicht zurückgegeben werden sollen (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Um eine WHERE Klausel in die SELECT Anweisung einzuschließen, klicken Sie auf die WHERE Schaltfläche, die das Dialogfeld "Klausel hinzufügen WHERE " anzeigt (siehe Abbildung 2). Wenn Sie einen Parameter hinzufügen möchten, um die von der SELECT Abfrage zurückgegebenen Ergebnisse einzuschränken, wählen Sie zuerst die Spalte aus, nach der die Daten gefiltert werden sollen. Wählen Sie als Nächstes den Operator aus, der für die Filterung verwendet werden soll (=, <= <, >usw.). Wählen Sie schließlich die Quelle des Parameterwerts aus, z. B. aus der Abfragezeichenfolge oder dem Sitzungszustand. Klicken Sie nach dem Konfigurieren des Parameters auf die Schaltfläche "Hinzufügen", um ihn in die SELECT Abfrage einzuschließen.

In diesem Beispiel geben wir nur die Ergebnisse zurück, bei denen der UnitPrice Wert kleiner oder gleich 25,00 $ ist. Wählen Sie daher UnitPrice in der Dropdownliste "Spalte" und <= in der Dropdownliste "Operator" aus. Wenn Sie einen hartcodierten Parameterwert (z. B. $25,00) verwenden oder wenn der Parameterwert programmgesteuert angegeben werden soll, wählen Sie "Keine" aus der Dropdownliste "Quelle" aus. Geben Sie als Nächstes den hartcodierten Parameterwert in das Textfeld Wert 25.00 ein, und schließen Sie den Vorgang ab, indem Sie auf die Schaltfläche "Hinzufügen" klicken.

Einschränken der ergebnisse, die aus dem Dialogfeld

Abbildung 2: Einschränken der ergebnisse, die aus dem Dialogfeld "Klausel hinzufügen WHERE " zurückgegeben werden (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Klicken Sie nach dem Hinzufügen des Parameters auf "OK", um zum Assistenten "Datenquelle konfigurieren" zurückzukehren. Die SELECT Anweisung am unteren Rand des Assistenten sollte nun eine WHERE Klausel mit einem Parameter mit dem Namen @UnitPrice" enthalten:

SELECT [ProductID], [ProductName], [UnitPrice]
FROM [Products]
WHERE ([UnitPrice] <= @UnitPrice)

Hinweis

Wenn Sie mehrere Bedingungen in der WHERE Klausel aus dem Dialogfeld "Klausel hinzufügen WHERE " angeben, verknüpft der Assistent sie mit dem AND Operator. Wenn Sie ein OR in die WHERE Klausel einschließen müssen (z. B. WHERE UnitPrice <= @UnitPrice OR Discontinued = 1), müssen Sie die SELECT Anweisung über den benutzerdefinierten SQL-Anweisungsbildschirm erstellen.

Konfigurieren Sie die SqlDataSource (klicken Sie auf Weiter, dann fertig stellen), und prüfen Sie dann das deklarative Markup von SqlDataSource. Das Markup umfasst nun eine <SelectParameters> Sammlung, die die Quellen für die Parameter in der SelectCommand darstellt.

<asp:SqlDataSource ID="Products25BucksAndUnderDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand=
        "SELECT [ProductID], [ProductName], [UnitPrice]
        FROM [Products] WHERE ([UnitPrice] <= @UnitPrice)">
    <SelectParameters>
        <asp:Parameter DefaultValue="25.00" Name="UnitPrice" Type="Decimal" />
    </SelectParameters>
</asp:SqlDataSource>

Wenn die SqlDataSource-Methode Select() aufgerufen wird, wird der UnitPrice Parameterwert (25.00) auf den Parameter in der @UnitPriceSelectCommand Datenbank angewendet, bevor er an die Datenbank gesendet wird. Das Nettoergebnis ist, dass nur die Produkte, die kleiner oder gleich 25,00 $ sind, aus der Products Tabelle zurückgegeben werden. Um dies zu bestätigen, fügen Sie der Seite eine GridView hinzu, binden Sie sie an diese Datenquelle, und zeigen Sie die Seite dann über einen Browser an. Sie sollten nur die Produkte sehen, die weniger als oder gleich 25,00 $ sind, wie in Abbildung 3 bestätigt wird.

Nur die Produkte, die kleiner als oder gleich 25,00 $ sind, werden angezeigt.

Abbildung 3: Nur diese Produkte, die kleiner oder gleich 25,00 $ sind, werden angezeigt (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Schritt 2: Hinzufügen von Parametern zu einer benutzerdefinierten SQL-Anweisung

Beim Hinzufügen einer benutzerdefinierten SQL-Anweisung können Sie die WHERE Klausel explizit eingeben oder einen Wert in der Zelle "Filter" des Abfrage-Generators angeben. Um dies zu veranschaulichen, zeigen wir nur die Produkte in einer GridView an, deren Preise kleiner als ein bestimmter Schwellenwert sind. Fügen Sie der ParameterizedQueries.aspx Seite zunächst ein Textfeld hinzu, um diesen Schwellenwert vom Benutzer zu erfassen. Legen Sie die Eigenschaft der TextBox ID auf MaxPrice fest. Fügen Sie ein Schaltflächenweb-Steuerelement hinzu, und legen Sie dessen Text Eigenschaft auf "Übereinstimmende Produkte anzeigen" fest.

Ziehen Sie als Nächstes ein GridView-Steuerelement auf die Seite, und wählen Sie im Smart Tag die Option zum Erstellen einer neuen SqlDataSource namens ProductsFilteredByPriceDataSource. Im Assistenten "Datenquelle konfigurieren" fahren Sie mit der Seite "Angeben einer benutzerdefinierten SQL-Anweisung oder gespeicherten Prozedur" fort (siehe Abbildung 4) und geben Sie die folgende Abfrage ein:

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice

Klicken Sie nach der Eingabe der Abfrage (manuell oder über den Abfrage-Generator) auf "Weiter".

Nur die Produkte zurückgeben, die kleiner oder gleich einem Parameterwert sind

Abbildung 4: Nur die Produkte zurückgeben, die kleiner oder gleich einem Parameterwert sind (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Da die Abfrage Parameter enthält, fordert der nächste Bildschirm im Assistenten uns zur Quelle der Parameterwerte auf. Wählen Sie "Control" aus der Dropdown-Liste für die Parameterquelle und MaxPrice (den Wert des TextBox-Controls ID ) aus der Dropdown-Liste für die ControlID. Sie können auch einen optionalen Standardwert eingeben, der verwendet werden soll, wenn der Benutzer keinen Text in das MaxPrice Textfeld eingegeben hat. Geben Sie vorerst keinen Standardwert ein.

Die TextBox-Eigenschaft

Abbildung 5: Die MaxPrice TextBox-Eigenschaft Text wird als Parameterquelle verwendet (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Schließen Sie den Assistenten zum Konfigurieren der Datenquelle ab, indem Sie auf "Weiter" und anschließend auf "Fertig stellen" klicken. Das deklarative Markup für GridView, TextBox, Button und SqlDataSource folgt:

Maximum price:
$<asp:TextBox ID="MaxPrice" runat="server" Columns="5" />
 
<asp:Button ID="DisplayProductsLessThanButton" runat="server"
    Text="Display Matching Products" />
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
    DataSourceID="ProductsFilteredByPriceDataSource" EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            HtmlEncode="False" DataFormatString="{0:c}"
            SortExpression="UnitPrice" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="ProductsFilteredByPriceDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand=
        "SELECT ProductName, UnitPrice 
        FROM Products WHERE UnitPrice <= @MaximumPrice">
    <SelectParameters>
        <asp:ControlParameter ControlID="MaxPrice" Name="MaximumPrice"
            PropertyName="Text" />
    </SelectParameters>
</asp:SqlDataSource>

Beachten Sie, dass der Parameter im Abschnitt "SqlDataSource" <SelectParameters> ein ControlParameter ist, der zusätzliche Eigenschaften wie ControlID und PropertyName umfasst. Wenn die Methode Select() der SqlDataSource aufgerufen wird, holt ControlParameter den Wert aus der angegebenen Eigenschaft des Websteuerelements und weist ihn dem entsprechenden Parameter in SelectCommand zu. In diesem Beispiel wird die MaxPrice Text-Eigenschaft als @MaxPrice Parameterwert verwendet.

Nehmen Sie sich eine Minute Zeit, um diese Seite über einen Browser anzuzeigen. Wenn Sie die Seite zum ersten Mal besuchen oder wenn das MaxPrice TextBox-Objekt keinen Wert aufweist, werden keine Datensätze in gridView angezeigt.

Es werden keine Datensätze angezeigt, wenn das MaxPrice-Textfeld leer ist.

Abbildung 6: Es werden keine Datensätze angezeigt, wenn das MaxPrice Textfeld leer ist (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Der Grund, warum keine Produkte angezeigt werden, ist, dass standardmäßig eine leere Zeichenfolge für einen Parameterwert in einen Datenbankwert NULL konvertiert wird. Da der Vergleich von [UnitPrice] <= NULL immer als falsch ausgewertet wird, werden keine Ergebnisse zurückgegeben.

Geben Sie einen Wert in das Textfeld ein, z. B. 5,00, und klicken Sie auf die Schaltfläche "Übereinstimmende Produkte anzeigen". Bei einem Postback informiert die SqlDataSource die GridView darüber, dass eine ihrer Parameterquellen geändert wurde. Folglich wird die GridView erneut mit der SqlDataSource verbunden und zeigt jene Produkte an, die weniger als oder gleich 5,00 $ kosten.

Produkte, die kleiner oder gleich 5,00 $ sind, werden angezeigt

Abbildung 7: Produkte, die kleiner als oder gleich 5,00 $ sind, werden angezeigt (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Anfängliches Anzeigen aller Produkte

Anstatt beim ersten Laden der Seite keine Produkte anzuzeigen, möchten wir möglicherweise alle Produkte anzeigen. Eine Möglichkeit zum Auflisten aller Produkte, wenn das MaxPrice TextBox-Objekt leer ist, besteht darin, den Standardwert des Parameters auf einen unsinnig hohen Wert festzulegen, z. B. 1000000, da es unwahrscheinlich ist, dass Northwind Traders jemals über Lagerbestände verfügen, deren Einzelpreis 1.000.000 $ überschreitet. Dieser Ansatz ist jedoch kurzsichtig und funktioniert in anderen Situationen möglicherweise nicht.

In früheren Lernprogrammen – Deklarative Parameter und Master/Detail-Filterung mit einem DropDownList-Element waren wir mit einem ähnlichen Problem konfrontiert. Unsere Lösung bestand darin, diese Logik in die Geschäftslogikebene zu setzen. Insbesondere untersuchte die BLL den eingehenden Wert, und wenn er NULL oder ein reservierter Wert war, wurde der Aufruf an die DAL-Methode weitergeleitet, die alle Datensätze zurückgibt. Wenn der eingehende Wert ein normaler Filterwert war, wurde ein Aufruf der DAL-Methode ausgeführt, die eine SQL-Anweisung ausgeführt hat, die eine parametrisierte WHERE Klausel mit dem angegebenen Wert verwendet hat.

Leider umgehen wir die Architektur bei Verwendung von SqlDataSource. Stattdessen müssen wir die SQL-Anweisung so anpassen, dass alle Datensätze intelligent abgerufen werden, wenn der @MaximumPrice Parameter oder ein reservierter Wert ist NULL . Für diese Übung haben wir es so, dass, wenn der @MaximumPrice Parameter gleich -1.0ist, alle Datensätze zurückgegeben werden sollen (-1.0 funktioniert als reservierter Wert, da kein Produkt einen negativen UnitPrice Wert haben kann). Dazu können wir die folgende SQL-Anweisung verwenden:

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice OR @MaximumPrice = -1.0

Diese WHERE Klausel gibt alle Datensätze zurück, wenn der @MaximumPrice Parameter gleich ist -1.0. Wenn der Parameterwert nicht -1.0ist, werden nur die Produkte zurückgegeben, deren UnitPrice Wert kleiner oder gleich dem @MaximumPrice Parameterwert ist. Durch Festlegen des Standardwerts des @MaximumPrice-Parameters auf -1.0 erhält MaxPrice beim ersten Laden der Seite (oder wenn die @MaximumPrice TextBox leer ist) den Wert -1.0, und alle Produkte werden angezeigt.

Jetzt werden alle Produkte angezeigt, wenn das MaxPrice-Textfeld leer ist

Abbildung 8: Jetzt werden alle Produkte angezeigt, wenn das MaxPrice Textfeld leer ist (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Es gibt ein paar Vorbehalte, die mit diesem Ansatz zu beachten sind. Stellen Sie zunächst fest, dass der Datentyp des Parameters von der Verwendung in der SQL-Abfrage abgeleitet wird. Wenn Sie die WHERE Klausel von @MaximumPrice = -1.0 auf @MaximumPrice = -1 ändern, behandelt die Laufzeitumgebung den Parameter als ganze Zahl. Wenn Sie dann versuchen, das MaxPrice TextBox-Objekt einem Dezimalwert (z. B. 5,00) zuzuweisen, tritt ein Fehler auf, da 5,00 nicht in eine ganze Zahl konvertiert werden kann. Um dies zu beheben, stellen Sie entweder sicher, dass Sie @MaximumPrice = -1.0 in der WHERE-Klausel verwenden oder, besser noch, die Eigenschaft des ControlParameter-Objekts Type auf Dezimal festlegen.

Zweitens kann die Abfrage-Engine durch die Aufnahme von OR @MaximumPrice = -1.0 in die WHERE Klausel keinen Index auf UnitPrice verwenden, falls dieser existiert, wodurch ein Tabellenscan entsteht. Dies kann sich auf die Leistung auswirken, wenn eine ausreichend große Anzahl von Datensätzen in der Products Tabelle vorhanden ist. Ein besserer Ansatz wäre das Verschieben dieser Logik in eine gespeicherte Prozedur, bei der eine IF Anweisung entweder eine SELECT Abfrage aus der Products Tabelle ohne WHERE Klausel ausführt, wenn alle Datensätze zurückgegeben werden müssen oder eine Klausel, deren WHERE Klausel nur die UnitPrice Kriterien enthält, sodass ein Index verwendet werden kann.

Schritt 3: Erstellen und Verwenden parametrisierter gespeicherter Prozeduren

Gespeicherte Prozeduren können eine Reihe von Eingabeparametern enthalten, die dann in den in der gespeicherten Prozedur definierten SQL-Anweisungen verwendet werden können. Beim Konfigurieren der SqlDataSource für die Verwendung einer gespeicherten Prozedur, die Eingabeparameter akzeptiert, können diese Parameterwerte mit denselben Techniken wie bei Ad-hoc-SQL-Anweisungen angegeben werden.

Um die Verwendung gespeicherter Prozeduren in sqlDataSource zu veranschaulichen, erstellen wir eine neue gespeicherte Prozedur in der Northwind-Datenbank namens GetProductsByCategory, die einen Parameter namens @CategoryID akzeptiert und alle Spalten der Produkte zurückgibt, deren CategoryID Spalten übereinstimmen @CategoryID. Um eine gespeicherte Prozedur zu erstellen, wechseln Sie zum Server-Explorer, und führen Sie einen Drilldown in die NORTHWND.MDF Datenbank durch. (Wenn der Server-Explorer nicht angezeigt wird, rufen Sie ihn auf, indem Sie zum Menü "Ansicht" wechseln und die Option "Server-Explorer" auswählen.)

Klicken Sie in der Datenbank mit der NORTHWND.MDF rechten Maustaste auf den Ordner "Gespeicherte Prozeduren", wählen Sie "Neue gespeicherte Prozedur hinzufügen" aus, und geben Sie die folgende Syntax ein:

CREATE PROCEDURE dbo.GetProductsByCategory
(
      @CategoryID int
)
AS
SELECT *
FROM Products
WHERE CategoryID = @CategoryID

Klicken Sie auf das Symbol "Speichern" (oder STRG+S), um die gespeicherte Prozedur zu speichern. Sie können die gespeicherte Prozedur testen, indem Sie im Ordner "Gespeicherte Prozeduren" mit der rechten Maustaste darauf klicken und "Ausführen" auswählen. Dadurch werden Sie aufgefordert, die Parameter der gespeicherten Prozedur (@CategoryIDin dieser Instanz) einzugeben, nach der die Ergebnisse im Ausgabefenster angezeigt werden.

Abbildung 9: Die GetProductsByCategory gespeicherte Prozedur, wenn sie mit einer @CategoryID von 1 ausgeführt wird (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Lassen Sie uns dieses gespeicherte Verfahren verwenden, um alle Produkte in der Kategorie "Getränke" in einer GridView anzuzeigen. Fügen Sie der Seite eine neue GridView hinzu, und binden Sie sie an eine neue SqlDataSource mit dem Namen BeverageProductsDataSource. Fahren Sie mit dem Bildschirm "Angeben einer benutzerdefinierten SQL-Anweisung oder gespeicherten Prozedur" fort, wählen Sie das Optionsfeld "Gespeicherte Prozedur" aus, und wählen Sie die GetProductsByCategory gespeicherte Prozedur aus der Dropdownliste aus.

Wählen Sie die gespeicherte Prozedur

Abbildung 10: Auswählen der GetProductsByCategory gespeicherten Prozedur aus der liste Drop-Down (Klicken Sie hier, um das Bild mit voller Größe anzuzeigen)

Da die gespeicherte Prozedur einen Eingabeparameter akzeptiert (@CategoryID), führt uns durch Klicken auf "Weiter" dazu, die Quelle für den Wert dieses Parameters anzugeben. Die Getränke CategoryID sind 1, lassen Sie also die Dropdownliste "Parameterquelle" bei "None" und geben Sie "1" in das Textfeld "DefaultValue" ein.

Verwenden Sie einen Hard-Coded Wert von 1, um die Produkte in der Kategorie

Abbildung 11: Verwenden eines Hard-Coded Werts von 1, um die Produkte in der Kategorie "Getränke" zurückzugeben (Klicken Sie hier, um das Bild mit voller Größe anzuzeigen)

Wie das folgende deklarative Markup zeigt, wird die SqlDataSource-Eigenschaft SelectCommand bei Verwendung einer gespeicherten Prozedur auf den Namen der gespeicherten Prozedur festgelegt, und die SelectCommandType Eigenschaft wird auf festgelegt StoredProcedure, wobei angegeben wird, dass es sich SelectCommand um den Namen einer gespeicherten Prozedur anstelle einer Ad-hoc-SQL-Anweisung handelt.

<asp:SqlDataSource ID="BeverageProductsDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

Testen Sie die Seite in einem Browser. Nur die Produkte, die zur Kategorie "Getränke" gehören, werden angezeigt, obwohl alle Produktfelder angezeigt werden, da die GetProductsByCategory gespeicherte Prozedur alle Spalten aus der Products Tabelle zurückgibt. Natürlich können wir die felder einschränken oder anpassen, die im GridView-Dialogfeld "Spalten bearbeiten" angezeigt werden.

Alle Getränke werden angezeigt

Abbildung 12: Alle Getränke werden angezeigt (Zum Anzeigen des Bilds mit voller Größe klicken)

Schritt 4: Programmgesteuertes Aufrufen der Select() -Anweisung einer SqlDataSource

Die Beispiele, die wir im vorherigen Lernprogramm und bisher in diesem Lernprogramm gesehen haben, haben SqlDataSource-Steuerelemente direkt an ein GridView gebunden. Auf die Daten des SqlDataSource-Steuerelements kann jedoch programmgesteuert zugegriffen und im Quellcode aufgezählt werden. Dies kann besonders nützlich sein, wenn Sie Daten abfragen müssen, um sie zu prüfen, aber nicht anzeigen müssen. Anstatt den gesamten Textbaustein ADO.NET Code schreiben zu müssen, um eine Verbindung mit der Datenbank herzustellen, den Befehl anzugeben und die Ergebnisse abzurufen, können Sie die SqlDataSource diesen monotonen Code behandeln lassen.

Um die programmgesteuerte Arbeit mit den SqlDataSource-Daten zu veranschaulichen, stellen Sie sich vor, dass Ihr Vorgesetzter Sie mit einer Anforderung zum Erstellen einer Webseite angegangen hat, die den Namen einer zufällig ausgewählten Kategorie und der zugehörigen Produkte anzeigt. Das heißt, wenn ein Benutzer diese Seite besucht, möchten wir zufällig eine Kategorie aus der Categories Tabelle auswählen, den Kategorienamen anzeigen und dann die Produkte auflisten, die zu dieser Kategorie gehören.

Dazu benötigen wir zwei SqlDataSource-Steuerelemente, um eine zufällige Kategorie aus der Categories Tabelle und eine andere abzurufen, um die Produkte der Kategorie abzurufen. Wir erstellen die SqlDataSource, die in diesem Schritt einen zufälligen Kategoriedatensatz abruft. Schritt 5 befasst sich mit dem Erstellen der SqlDataSource, die die Produkte der Kategorie abruft.

Fügen Sie zunächst eine SqlDataSource zu ParameterizedQueries.aspx hinzu und legen Sie ihre Eigenschaft ID auf RandomCategoryDataSource fest. Konfigurieren Sie sie so, dass sie die folgende SQL-Abfrage verwendet:

SELECT TOP 1 CategoryID, CategoryName
FROM Categories
ORDER BY NEWID()

ORDER BY NEWID() gibt die datensätze in zufälliger Reihenfolge sortiert zurück (siehe Verwenden NEWID() zur zufälligen Sortierung von Datensätzen). SELECT TOP 1 gibt den ersten Datensatz aus dem Resultset zurück. Diese Abfrage gibt die Spaltenwerte von CategoryID und CategoryName aus einer einzelnen, zufällig ausgewählten Kategorie zurück.

Wenn Sie den Wert der Kategorie CategoryName anzeigen möchten, fügen Sie der Seite ein Websteuerelement vom Typ 'Label' hinzu, legen Sie dessen ID Eigenschaft auf CategoryNameLabel fest, und löschen Sie dessen Text Eigenschaft. Um die Daten programmgesteuert aus einem SqlDataSource-Steuerelement abzurufen, müssen wir seine Select() Methode aufrufen. Die Select() Methode erwartet einen einzelnen Eingabeparameter vom Typ DataSourceSelectArguments, der angibt, wie die Daten vor der Rückgabe angezeigt werden sollen. Dies kann Anweisungen zum Sortieren und Filtern der Daten enthalten und wird von den Datenwebsteuerelementen beim Sortieren oder Ausblättern der Daten aus einem SqlDataSource-Steuerelement verwendet. In unserem Beispiel müssen die Daten jedoch nicht geändert werden, bevor sie zurückgegeben werden. Daher wird das DataSourceSelectArguments.Empty Objekt übergeben.

Die Select() Methode gibt ein Objekt zurück, das IEnumerable implementiert. Der zurückgegebene genaue Typ hängt vom Wert der Eigenschaft des SqlDataSource-Steuerelements DataSourceMode ab. Wie im vorherigen Tutorial erläutert, kann diese Eigenschaft entweder auf einen Wert von DataSet oder DataReader gesetzt werden. Bei Festlegung auf DataSet, gibt die Select() Methode ein DataView -Objekt zurück; wenn festgelegt auf DataReader, wird ein Objekt zurückgegeben, das implementiert IDataReaderwird. Da die SqlDataSource ihre RandomCategoryDataSource-Eigenschaft auf DataSourceMode (der Standardeinstellung) gesetzt hat, werden wir mit einem DataView-Objekt arbeiten.

Der folgende Code veranschaulicht, wie die Datensätze aus der RandomCategoryDataSource SqlDataSource als DataView abgerufen und wie der CategoryName Spaltenwert aus der ersten DataView-Zeile gelesen wird:

protected void Page_Load(object sender, EventArgs e)
{
    // Get the data from the SqlDataSource as a DataView
    DataView randomCategoryView =
        (DataView)RandomCategoryDataSource.Select(DataSourceSelectArguments.Empty);
    if (randomCategoryView.Count > 0)
    {
        // Assign the CategoryName value to the Label
        CategoryNameLabel.Text =
            string.Format("Here are Products in the {0} Category...",
                randomCategoryView[0]["CategoryName"].ToString());
    }
}

randomCategoryView[0] gibt das erste DataRowView in der DataView zurück. randomCategoryView[0]["CategoryName"] gibt den Wert der CategoryName Spalte in dieser ersten Zeile zurück. Beachten Sie, dass DataView schwach typisiert ist. Um auf einen bestimmten Spaltenwert zu verweisen, müssen wir den Namen der Spalte als Zeichenfolge übergeben ( CategoryName, in diesem Fall). Abbildung 13 zeigt die Meldung, die CategoryNameLabel beim Anzeigen der Seite angezeigt wird. Natürlich wird der angezeigte Kategoriename zufällig ausgewählt von der RandomCategoryDataSource SqlDataSource bei jedem Besuch der Seite, einschließlich Postbacks.

Der Name der zufällig ausgewählten Kategorie wird angezeigt.

Abbildung 13: Der Name der zufällig ausgewählten Kategorie wird angezeigt (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Hinweis

Wenn die Eigenschaft des SqlDataSource-Steuerelements DataSourceMode auf DataReader festgelegt worden wäre, müsste der Rückgabewert aus der Select()-Methode in IDataReader umgewandelt werden. Um den CategoryName Spaltenwert aus der ersten Zeile zu lesen, verwenden wir Code wie folgt:

if (randomCategoryReader.Read())
{
   string categoryName = randomCategoryReader["CategoryName"].ToString();
   ...
}

Wenn SqlDataSource eine Kategorie zufällig auswählt, können wir die GridView hinzufügen, die die Produkte der Kategorie auflistet.

Hinweis

Anstatt ein Label-Webkontrollelement zum Anzeigen des Kategorienamens zu verwenden, hätten wir der Seite eine FormView oder DetailsView hinzufügen und an die SqlDataSource binden können. Mithilfe der Bezeichnung konnten wir jedoch untersuchen, wie die SqlDataSource-Anweisung Select() programmgesteuert aufgerufen und mit den resultierenden Daten im Code gearbeitet wird.

Schritt 5: Programmgesteuertes Zuweisen von Parameterwerten

Alle Beispiele, die wir bisher in diesem Lernprogramm gesehen haben, haben entweder einen hartcodierten Parameterwert oder einen aus einer der vordefinierten Parameterquellen (ein Abfragezeichenfolgenwert, ein Websteuerelement auf der Seite usw.) verwendet. Die Parameter des SqlDataSource-Steuerelements können jedoch auch programmgesteuert festgelegt werden. Zum Abschließen des aktuellen Beispiels benötigen wir eine SqlDataSource, die alle Produkte zurückgibt, die zu einer angegebenen Kategorie gehören. Diese SqlDataSource verfügt über einen CategoryID Parameter, dessen Wert basierend auf dem CategoryID von der RandomCategoryDataSource SqlDataSource im Page_Load Ereignishandler zurückgegebenen Spaltenwert festgelegt werden muss.

Beginnen Sie, indem Sie der Seite eine GridView hinzufügen und an eine neue SqlDataSource mit dem Namen ProductsByCategoryDataSourcebinden. Ähnlich wie in Schritt 3 konfigurieren Sie die SqlDataSource so, dass sie die GetProductsByCategory gespeicherte Prozedur aufruft. Lassen Sie die Dropdownliste "Parameterquelle" auf "Keine" festgelegt, geben Sie jedoch keinen Standardwert ein, da wir diesen Standardwert programmgesteuert festlegen.

Screenshot des Fensters

Abbildung 14: Keine Parameterquelle oder keinen Standardwert angeben (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Nach Abschluss des SqlDataSource-Assistenten sollte das resultierende deklarative Markup ähnlich wie folgt aussehen:

<asp:SqlDataSource ID="ProductsByCategoryDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter Name="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

Wir können den DefaultValue-Parameter des CategoryID programmgesteuert im Ereignishandler des Page_Load zuweisen.

// Assign the ProductsByCategoryDataSource's
// CategoryID parameter's DefaultValue property
ProductsByCategoryDataSource.SelectParameters["CategoryID"].DefaultValue =
    randomCategoryView[0]["CategoryID"].ToString();

Mit dieser Ergänzung enthält die Seite eine GridView, die die Produkte anzeigt, die der zufällig ausgewählten Kategorie zugeordnet sind.

Screenshot der Seite

Abbildung 15: Keine Parameterquelle oder keinen Standardwert angeben (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Zusammenfassung

Mit SqlDataSource können Seitenentwickler parametrisierte Abfragen definieren, deren Parameterwerte hartcodiert, aus vordefinierten Parameterquellen abgerufen oder programmgesteuert zugewiesen werden können. In diesem Lernprogramm haben wir erfahren, wie Sie eine parametrisierte Abfrage aus dem Assistenten zum Konfigurieren von Datenquellen für Ad-hoc-SQL-Abfragen und gespeicherte Prozeduren erstellen. Außerdem haben wir die Verwendung hartcodierter Parameterquellen, eines Websteuerelements als Parameterquelle und die programmgesteuerte Angabe des Parameterwerts untersucht.

Wie bei objectDataSource bietet die SqlDataSource auch Funktionen zum Ändern der zugrunde liegenden Daten. Im nächsten Lernprogramm werden wir uns damit befassen, wie man INSERT, UPDATE, und DELETE-Anweisungen mit dem SqlDataSource definiert. Nachdem diese Anweisungen hinzugefügt wurden, können wir die integrierten Einfüge-, Bearbeitungs- und Löschfunktionen verwenden, die den GridView-, DetailsView- und FormView-Steuerelementen inhärent sind.

Glückliche Programmierung!

Zum Autor

Scott Mitchell, Autor von sieben ASP/ASP.NET Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann bei mitchell@4GuysFromRolla.comerreicht werden.

Besonderer Dank an

Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Leitende Prüfer für dieses Lernprogramm waren Scott Clyde, Randell Schmidt und Ken Pespisa. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.