Share via


Datenquellen-Steuerelemente

von Microsoft

Das DataGrid-Steuerelement in ASP.NET 1.x hat den Datenzugriff in Webanwendungen erheblich verbessert. Es war jedoch nicht so benutzerfreundlich, wie es hätte sein können. Es erforderte immer noch eine beträchtliche Menge an Code, um viele nützliche Funktionen daraus zu erhalten. Dies ist das Modell in allen Datenzugriffsbemühungen in 1.x.

Das DataGrid-Steuerelement in ASP.NET 1.x hat den Datenzugriff in Webanwendungen erheblich verbessert. Es war jedoch nicht so benutzerfreundlich, wie es hätte sein können. Es erforderte immer noch eine beträchtliche Menge an Code, um viele nützliche Funktionen daraus zu erhalten. Dies ist das Modell in allen Datenzugriffsbemühungen in 1.x.

ASP.NET 2.0 behandelt dies teilweise mit Datenquellensteuerelementen. Die Datenquellensteuerelemente in ASP.NET 2.0 stellen Entwicklern ein deklaratives Modell zum Abrufen von Daten, anzeigen und Bearbeiten von Daten bereit. Der Zweck von Datenquellensteuerelementen besteht darin, datengebundenen Steuerelementen unabhängig von der Quelle dieser Daten eine konsistente Darstellung von Daten bereitzustellen. Das Herzstück der Datenquellensteuerelemente in ASP.NET 2.0 ist die abstrakte DataSourceControl-Klasse. Die DataSourceControl-Klasse stellt eine Basisimplementierung der IDataSource-Schnittstelle und der IListSource-Schnittstelle bereit, mit deren Hilfe Sie das Datenquellensteuerelement als DataSource eines datengebundenen Steuerelements zuweisen können (über die neue DataSourceId-Eigenschaft, die weiter unten erläutert wird) und die darin enthaltenen Daten als Liste verfügbar machen können. Jede Liste von Daten aus einem Datenquellensteuerelement wird als DataSourceView-Objekt verfügbar gemacht. Der Zugriff auf die DataSourceView-Instanzen wird über die IDataSource-Schnittstelle bereitgestellt. Beispielsweise gibt die GetViewNames-Methode eine ICollection zurück, mit der Sie die Einem bestimmten Datenquellensteuerelement zugeordneten DataSourceViews aufzählen können, und die GetView-Methode ermöglicht Ihnen den Zugriff auf eine bestimmte DataSourceView-instance anhand des Namens.

Datenquellensteuerelemente verfügen über keine Benutzeroberfläche. Sie werden als Serversteuerelemente implementiert, sodass sie deklarative Syntax unterstützen und bei Bedarf Zugriff auf den Seitenzustand haben. Datenquellensteuerelemente rendern kein HTML-Markup für den Client.

Hinweis

Wie Sie später sehen werden, gibt es auch Zwischenspeicherungsvorteile, die durch die Verwendung von Datenquellensteuerelementen erzielt werden.

Speichern von Verbindungszeichenfolgen

Bevor wir uns mit der Konfiguration von Datenquellensteuerelementen befassen, sollten wir eine neue Funktion in ASP.NET 2.0 zu Verbindungszeichenfolgen behandeln. ASP.NET 2.0 wird ein neuer Abschnitt in der Konfigurationsdatei eingeführt, mit dem Sie Verbindungszeichenfolgen, die zur Laufzeit dynamisch gelesen werden können, problemlos speichern können. Der <Abschnitt connectionStrings> erleichtert das Speichern von Verbindungszeichenfolgen.

Der folgende Codeausschnitt fügt eine neue Verbindungszeichenfolge hinzu.

<connectionStrings> <add name="Northwind" connectionString="Data Source=localhost; Integrated Security=SSPI;Initial Catalog=Northwind;" providerName="System.Data.SqlClient" /> </connectionStrings>

Hinweis

Genau wie beim <Abschnitt appSettings> wird der <Abschnitt connectionStrings> außerhalb des <Abschnitts system.web> in der Konfigurationsdatei angezeigt.

Um diese Verbindungszeichenfolge zu verwenden, können Sie beim Festlegen des ConnectionString-Attributs eines Serversteuerelements die folgende Syntax verwenden.

ConnectionString="<%$ ConnectionStrings:Northwind%>"

Der <Abschnitt connectionStrings> kann auch verschlüsselt werden, sodass vertrauliche Informationen nicht verfügbar gemacht werden. Diese Fähigkeit wird in einem späteren Modul behandelt.

Zwischenspeichern von Datenquellen

Jedes DataSourceControl stellt vier Eigenschaften zum Konfigurieren der Zwischenspeicherung bereit. EnableCaching, CacheDuration, CacheExpirationPolicy und CacheKeyDependency.

Enablecaching

EnableCaching ist eine boolesche Eigenschaft, die bestimmt, ob das Zwischenspeichern für das Datenquellensteuerelement aktiviert ist.

CacheDuration-Eigenschaft

Die CacheDuration-Eigenschaft legt die Anzahl der Sekunden fest, für die der Cache gültig bleibt. Wenn Sie diese Eigenschaft auf 0 festlegen, bleibt der Cache gültig, bis er explizit ungültig wird.

CacheExpirationPolicy-Eigenschaft

Die CacheExpirationPolicy-Eigenschaft kann entweder auf Absolute oder Sliding festgelegt werden. Wenn Sie ihn auf Absolute festlegen, bedeutet dies, dass die maximale Zeitspanne, für die die Daten zwischengespeichert werden, die Anzahl von Sekunden ist, die von der CacheDuration-Eigenschaft angegeben wird. Wenn sie auf Gleiten festgelegt wird, wird die Ablaufzeit zurückgesetzt, wenn die einzelnen Vorgänge ausgeführt werden.

CacheKeyDependency-Eigenschaft

Wenn ein Zeichenfolgenwert für die CacheKeyDependency-Eigenschaft angegeben wird, richtet ASP.NET basierend auf dieser Zeichenfolge eine neue Cacheabhängigkeit ein. Dadurch können Sie den Cache explizit ungültig machen, indem Sie die CacheKeyDependency einfach ändern oder entfernen.

Wichtig: Wenn der Identitätswechsel aktiviert ist und der Zugriff auf die Datenquelle und/oder den Inhalt der Daten auf der Clientidentität basiert, empfiehlt es sich, die Zwischenspeicherung zu deaktivieren, indem Sie EnableCaching auf False festlegen. Wenn die Zwischenspeicherung in diesem Szenario aktiviert ist und ein anderer Benutzer als der Benutzer, der die Daten ursprünglich angefordert hat, eine Anforderung ausgibt, wird die Autorisierung für die Datenquelle nicht erzwungen. Die Daten werden einfach aus dem Cache bereitgestellt.

Das SqlDataSource-Steuerelement

Mit dem SqlDataSource-Steuerelement kann ein Entwickler auf Daten zugreifen, die in einer relationalen Datenbank gespeichert sind, die ADO.NET unterstützt. Es kann den System.Data.SqlClient-Anbieter verwenden, um auf eine SQL Server-Datenbank, den System.Data.OleDb-Anbieter, den System.Data.Odbc-Anbieter oder den System.Data.OracleClient-Anbieter für den Zugriff auf Oracle zuzugreifen. Daher wird die SqlDataSource sicherlich nicht nur für den Zugriff auf Daten in einer SQL Server-Datenbank verwendet.

Um sqlDataSource zu verwenden, geben Sie einfach einen Wert für die ConnectionString-Eigenschaft an und geben einen SQL-Befehl oder eine gespeicherte Prozedur an. Das SqlDataSource-Steuerelement kümmert sich um die Arbeit mit der zugrunde liegenden ADO.NET architektur. Es öffnet die Verbindung, fragt die Datenquelle ab oder führt die gespeicherte Prozedur aus, gibt die Daten zurück und schließt dann die Verbindung für Sie.

Hinweis

Da die DataSourceControl-Klasse die Verbindung automatisch für Sie schließt, sollte die Anzahl der Kundenanrufe reduziert werden, die durch das Verlusten von Datenbankverbindungen generiert werden.

Der folgende Codeausschnitt bindet ein DropDownList-Steuerelement mithilfe der Verbindungszeichenfolge, die wie oben gezeigt in der Konfigurationsdatei gespeichert ist, an ein SqlDataSource-Steuerelement.

<asp:SqlDataSource id="SqlDataSource1" runat="server" DataSourceMode="DataReader" ConnectionString="<%$ ConnectionStrings:Northwind%>" SelectCommand="SELECT EmployeeID, LastName FROM Employees"> </asp:SqlDataSource><asp:DropDownList id="ListBox1" runat="server" DataTextField="LastName" DataValueField="EmployeeID" DataSourceID="SqlDataSource1"> </asp:DropDownList>

Wie oben dargestellt, gibt die DataSourceMode-Eigenschaft der SqlDataSource den Modus für die Datenquelle an. Im obigen Beispiel ist dataSourceMode auf DataReader festgelegt. In diesem Fall gibt sqlDataSource mithilfe eines vorwärtsgerichteten und schreibgeschützten Cursors ein IDataReader-Objekt zurück. Der angegebene Objekttyp, der zurückgegeben wird, wird durch den verwendeten Anbieter gesteuert. In diesem Fall verwende ich den System.Data.SqlClient-Anbieter, wie im <Abschnitt connectionStrings> der web.config-Datei angegeben. Daher ist das zurückgegebene Objekt vom Typ SqlDataReader. Durch Angeben eines DataSourceMode-Werts von DataSet können die Daten in einem DataSet auf dem Server gespeichert werden. In diesem Modus können Sie Features wie Sortierung, Paging usw. hinzufügen. Wenn ich die SqlDataSource an ein GridView-Steuerelement gebunden hätte, hätte ich den DataSet-Modus ausgewählt. Im Fall einer DropDownList ist jedoch der DataReader-Modus die richtige Wahl.

Hinweis

Beim Zwischenspeichern einer SqlDataSource oder einer AccessDataSource muss die DataSourceMode-Eigenschaft auf DataSet festgelegt werden. Eine Ausnahme tritt auf, wenn Sie die Zwischenspeicherung mit einem DataSourceMode-Objekt von DataReader aktivieren.

SqlDataSource-Eigenschaften

Im Folgenden sind einige der Eigenschaften des SqlDataSource-Steuerelements aufgeführt.

CancelSelectOnNullParameter

Ein boolescher Wert, der angibt, ob ein Select-Befehl abgebrochen wird, wenn einer der Parameter NULL ist. Der Standardwert lautet „true“.

Conflictdetection

In einer Situation, in der mehrere Benutzer eine Datenquelle gleichzeitig aktualisieren, bestimmt die ConflictDetection-Eigenschaft das Verhalten des SqlDataSource-Steuerelements. Diese Eigenschaft wird zu einem der Werte der ConflictOptions-Enumeration ausgewertet. Diese Werte sind CompareAllValues und OverwriteChanges. Bei Festlegung auf OverwriteChanges überschreibt die letzte Person, die Daten in die Datenquelle geschrieben hat, alle vorherigen Änderungen. Wenn die ConflictDetection-Eigenschaft jedoch auf CompareAllValues festgelegt ist, werden Parameter für die Spalten erstellt, die vom SelectCommand zurückgegeben werden, und parameter werden auch erstellt, um die ursprünglichen Werte in jeder dieser Spalten zu enthalten, sodass SqlDataSource bestimmen kann, ob sich die Werte seit der Ausführung von SelectCommand geändert haben.

Deletecommand

Legt die SQL-Zeichenfolge fest, die beim Löschen von Zeilen aus der Datenbank verwendet wird, oder ruft sie ab. Dies kann entweder eine SQL-Abfrage oder ein Name einer gespeicherten Prozedur sein.

DeleteCommandType

Legt den Typ des Delete-Befehls fest oder ruft diesen ab, entweder eine SQL-Abfrage (Text) oder eine gespeicherte Prozedur (StoredProcedure).

Deleteparameters

Gibt die Parameter zurück, die vom DeleteCommand des SqlDataSourceView-Objekts verwendet werden, das dem SqlDataSource-Steuerelement zugeordnet ist.

Oldvaluesparameterformatstring

Diese Eigenschaft wird verwendet, um das Format der ursprünglichen Wertparameter in Fällen anzugeben, in denen die ConflictDetection-Eigenschaft auf CompareAllValues festgelegt ist. Der Standardwert ist {0} , was bedeutet, dass die Ursprünglichen Wertparameter den gleichen Namen wie der ursprüngliche Parameter annehmen. Anders ausgedrückt: Wenn der Feldname EmployeeID lautet, wäre @EmployeeIDder ursprüngliche Wertparameter .

SelectCommand

Legt die SQL-Zeichenfolge fest, die zum Abrufen von Daten aus der Datenbank verwendet wird, oder ruft sie ab. Dies kann entweder eine SQL-Abfrage oder ein Name einer gespeicherten Prozedur sein.

Selectcommandtype

Legt den Typ des Select-Befehls fest, entweder eine SQL-Abfrage (Text) oder eine gespeicherte Prozedur (StoredProcedure).

Selectparameters

Gibt die Parameter zurück, die vom SelectCommand des SqlDataSourceView-Objekts verwendet werden, das dem SqlDataSource-Steuerelement zugeordnet ist.

Sortparametername

Ruft den Namen eines gespeicherten Prozedurparameters ab, der beim Sortieren der vom Datenquellensteuerelement abgerufenen Daten verwendet wird, oder legt diesen fest. Nur gültig, wenn SelectCommandType auf StoredProcedure festgelegt ist.

Sqlcachedependency

Eine durch Semikolons getrennte Zeichenfolge, die die Datenbanken und Tabellen angibt, die in einer SQL Server Cacheabhängigkeit verwendet werden. (SQL-Cacheabhängigkeiten werden in einem späteren Modul erläutert.)

Updatecommand

Legt die SQL-Zeichenfolge fest, die beim Aktualisieren von Daten in der Datenbank verwendet wird, oder ruft sie ab. Dies kann entweder eine SQL-Abfrage oder ein Name einer gespeicherten Prozedur sein.

UpdateCommandType

Legt fest oder ruft den Typ des Updatebefehls ab, entweder eine SQL-Abfrage (Text) oder eine gespeicherte Prozedur (StoredProcedure).

Updateparameters

Gibt die Parameter zurück, die vom UpdateCommand des SqlDataSourceView-Objekts verwendet werden, das dem SqlDataSource-Steuerelement zugeordnet ist.

Das AccessDataSource-Steuerelement

Das AccessDataSource-Steuerelement wird von der SqlDataSource-Klasse abgeleitet und zum Binden von Daten an eine Microsoft Access-Datenbank verwendet. Die ConnectionString-Eigenschaft für das AccessDataSource-Steuerelement ist eine schreibgeschützte Eigenschaft. Anstatt die ConnectionString-Eigenschaft zu verwenden, wird die DataFile-Eigenschaft verwendet, um auf die Access-Datenbank zu verweisen, wie unten gezeigt.

<asp:AccessDataSource id="AccessDataSource1" runat="server" DataFile="~/App_Data/Northwind.mdb"> </asp:AccessDataSource>

AccessDataSource legt den ProviderName der SqlDataSource-Basis immer auf System.Data.OleDb fest und stellt mithilfe des OLE DB-Anbieters Microsoft.Jet.OLEDB.4.0 eine Verbindung mit der Datenbank her. Sie können das AccessDataSource-Steuerelement nicht verwenden, um eine Verbindung mit einer kennwortgeschützten Access-Datenbank herzustellen. Wenn Sie eine Verbindung mit einer kennwortgeschützten Datenbank herstellen müssen, sollten Sie das SqlDataSource-Steuerelement verwenden.

Hinweis

Access-Datenbanken, die auf der Website gespeichert sind, sollten im Verzeichnis App_Data platziert werden. ASP.NET lässt das Durchsuchen von Dateien in diesem Verzeichnis nicht zu. Sie müssen dem Prozesskonto lese- und schreibberechtigungen für das verzeichnis App_Data erteilen, wenn Sie Access-Datenbanken verwenden.

Das XmlDataSource-Steuerelement

XmlDataSource wird verwendet, um XML-Daten an datengebundene Steuerelemente zu binden. Sie können eine Bindung an eine XML-Datei mithilfe der DataFile-Eigenschaft oder mithilfe der Data-Eigenschaft an eine XML-Zeichenfolge binden. XmlDataSource macht XML-Attribute als bindbare Felder verfügbar. In Fällen, in denen Sie an Werte binden müssen, die nicht als Attribute dargestellt werden, müssen Sie eine XSL-Transformation verwenden. Sie können auch XPath-Ausdrücke verwenden, um XML-Daten zu filtern.

Betrachten Sie die folgende XML-Datei:

<?xml version="1.0" encoding="utf-8" ?> <People> <Person FirstName="Jake" LastName="Stone"> <Address> <Street>345 Maple St.</Street> <City>Redmond</City> <Region>WA</Region> <ZipCode>01434</ZipCode> </Address> <Job> <Title>CEO</Title> <Description>Develops company strategies.</Description> </Job> </Person> <Person FirstName="Jacob" LastName="Ladder"> <Address> <Street>123 Elm St.</Street> <City>Seattle</City> <Region>WA</Region> <ZipCode>11223</ZipCode> </Address> <Job> <Title>Attorney</Title> <Description>Reviews legal issues.</Description> </Job> </Person> <Person FirstName="Angela" LastName="Hound"> <Address> <Street>34 Palm Avenue</Street> <City>Renton</City> <Region>WA</Region> <ZipCode>63910</ZipCode> </Address> <Job> <Title>IT Director</Title> <Description>In charge of corporate network.</Description> </Job> </Person> </People>

Beachten Sie, dass xmlDataSource eine XPath-Eigenschaft von Personen/Person verwendet, um nur nach den <Person-Knoten> zu filtern. DropDownList wird dann mithilfe der DataTextField-Eigenschaft an das LastName-Attribut gebunden.

Während das XmlDataSource-Steuerelement hauptsächlich zum Binden von Daten an schreibgeschützte XML-Daten verwendet wird, ist es möglich, die XML-Datendatei zu bearbeiten. Beachten Sie, dass in solchen Fällen das automatische Einfügen, Aktualisieren und Löschen von Informationen in der XML-Datei nicht automatisch erfolgt, wie dies bei anderen Datenquellensteuerelementen der Fall ist. Stattdessen müssen Sie Code schreiben, um die Daten mithilfe der folgenden Methoden des XmlDataSource-Steuerelements manuell zu bearbeiten.

GetXmlDocument

Ruft ein XmlDocument-Objekt ab, das den von der XmlDataSource abgerufenen XML-Code enthält.

Speichern

Speichert das In-Memory-XmlDocument wieder in der Datenquelle.

Es ist wichtig zu wissen, dass die Save-Methode nur funktioniert, wenn die folgenden beiden Bedingungen erfüllt sind:

  1. Die XmlDataSource verwendet die DataFile-Eigenschaft, um an eine XML-Datei zu binden, anstelle der Data-Eigenschaft, die an XML-Daten im Arbeitsspeicher gebunden werden soll.
  2. Über die Transform- oder TransformFile-Eigenschaft wird keine Transformation angegeben.

Beachten Sie auch, dass die Save-Methode unerwartete Ergebnisse liefern kann, wenn sie von mehreren Benutzern gleichzeitig aufgerufen wird.

Das ObjectDataSource-Steuerelement

Die Datenquellensteuerelemente, die wir bis zu diesem Punkt behandelt haben, sind hervorragende Wahlmöglichkeiten für Anwendungen mit zwei Ebenen, bei denen das Datenquellensteuerelement direkt mit dem Datenspeicher kommuniziert. Viele reale Anwendungen sind jedoch Anwendungen mit mehreren Ebenen, bei denen eine Datenquellensteuerung möglicherweise mit einem Geschäftsobjekt kommunizieren muss, das wiederum mit der Datenebene kommuniziert. In diesen Situationen füllt ObjectDataSource die Rechnung gut aus. Die ObjectDataSource funktioniert in Verbindung mit einem Quellobjekt. Das ObjectDataSource-Steuerelement erstellt eine instance des Quellobjekts, ruft die angegebene Methode auf und entfernt das Objekt instance alle innerhalb des Bereichs einer einzelnen Anforderung, wenn Ihr Objekt instance Methoden anstelle statischer Methoden (Shared in Visual Basic) aufweist. Daher muss Ihr Objekt zustandslos sein. Das heißt, Ihr Objekt sollte alle erforderlichen Ressourcen innerhalb einer einzelnen Anforderung abrufen und freigeben. Sie können steuern, wie das Quellobjekt erstellt wird, indem Sie das ObjectCreating-Ereignis des ObjectDataSource-Steuerelements behandeln. Sie können eine instance des Quellobjekts erstellen und dann die ObjectInstance-Eigenschaft der ObjectDataSourceEventArgs-Klasse auf diesen instance festlegen. Das ObjectDataSource-Steuerelement verwendet die instance, die im ObjectCreating-Ereignis erstellt wird, anstatt selbst eine instance zu erstellen.

Wenn das Quellobjekt für ein ObjectDataSource-Steuerelement öffentliche statische Methoden (Shared in Visual Basic) verfügbar macht, die aufgerufen werden können, um Daten abzurufen und zu ändern, ruft ein ObjectDataSource-Steuerelement diese Methoden direkt auf. Wenn ein ObjectDataSource-Steuerelement eine instance des Quellobjekts erstellen muss, um Methodenaufrufe auszuführen, muss das Objekt einen öffentlichen Konstruktor enthalten, der keine Parameter akzeptiert. Das ObjectDataSource-Steuerelement ruft diesen Konstruktor auf, wenn es eine neue instance des Quellobjekts erstellt.

Wenn das Quellobjekt keinen öffentlichen Konstruktor ohne Parameter enthält, können Sie eine instance des Quellobjekts erstellen, das vom ObjectDataSource-Steuerelement im ObjectCreating-Ereignis verwendet wird.

Angeben von Objektmethoden

Das Quellobjekt für ein ObjectDataSource-Steuerelement kann eine beliebige Anzahl von Methoden enthalten, die zum Auswählen, Einfügen, Aktualisieren oder Löschen von Daten verwendet werden. Diese Methoden werden vom ObjectDataSource-Steuerelement basierend auf dem Namen der Methode aufgerufen, wie mit der SelectMethod-, InsertMethod-, UpdateMethod- oder DeleteMethod-Eigenschaft des ObjectDataSource-Steuerelements identifiziert. Das Quellobjekt kann auch eine optionale SelectCount-Methode enthalten, die durch das ObjectDataSource-Steuerelement mithilfe der SelectCountMethod-Eigenschaft identifiziert wird, die die Anzahl der Gesamtanzahl der Objekte in der Datenquelle zurückgibt. Das ObjectDataSource-Steuerelement ruft die SelectCount-Methode auf, nachdem eine Select-Methode aufgerufen wurde, um die Gesamtzahl der Datensätze an der Datenquelle abzurufen, die beim Paging verwendet werden können.

Lab mit Datenquellensteuerelementen

Übung 1: Anzeigen von Daten mit dem SqlDataSource-Steuerelement

In der folgenden Übung wird das SqlDataSource-Steuerelement verwendet, um eine Verbindung mit der Northwind-Datenbank herzustellen. Es wird davon ausgegangen, dass Sie zugriff auf die Northwind-Datenbank auf einem SQL Server 2000-instance haben.

  1. Erstellen Sie eine neue ASP.NET-Website.

  2. Fügen Sie eine neue web.config-Datei hinzu.

    1. Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und klicken Sie auf Neues Element hinzufügen.
    2. Wählen Sie in der Liste der Vorlagen Webkonfigurationsdatei aus, und klicken Sie auf Hinzufügen.
  3. Bearbeiten Sie den <Abschnitt connectionStrings> wie folgt:

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ConnectionStrings:Northwind%>"
        SelectCommand="SELECT * FROM Products">
    </asp:SqlDataSource>
    
  4. Wechseln Sie zur Codeansicht, und fügen Sie dem <asp:SqlDataSource-Steuerelement> wie folgt ein ConnectionString-Attribut und ein SelectCommand-Attribut hinzu:

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ConnectionStrings:Northwind%>"
        SelectCommand="SELECT * FROM Products">
    </asp:SqlDataSource>
    
  5. Fügen Sie in der Entwurfsansicht ein neues GridView-Steuerelement hinzu.

  6. Wählen Sie im Menü GridView-Aufgaben in der Dropdownliste Datenquelle auswählen die Option SqlDataSource1 aus.

  7. Klicken Sie mit der rechten Maustaste auf Default.aspx, und wählen Sie im Menü Im Browser anzeigen aus. Klicken Sie auf Ja, wenn Sie zum Speichern aufgefordert werden.

  8. GridView zeigt die Daten aus der Tabelle Products an.

Übung 2: Bearbeiten von Daten mit dem SqlDataSource-Steuerelement

In der folgenden Übung wird veranschaulicht, wie Sie ein DropDownList-Steuerelement mithilfe der deklarativen Syntax binden und die im DropDownList-Steuerelement dargestellten Daten bearbeiten können.

  1. Löschen Sie in der Entwurfsansicht das GridView-Steuerelement aus Default.aspx.

    Wichtig: Belassen Sie das SqlDataSource-Steuerelement auf der Seite.

  2. Fügen Sie ein DropDownList-Steuerelement zu Default.aspx hinzu.

  3. Wechseln Sie zur Quellansicht.

  4. Fügen Sie dem <asp:DropDownList-Steuerelement> wie folgt ein DataSourceId-, DataTextField- und DataValueField-Attribut hinzu:

    <asp:DropDownList ID="ddlProducts" runat="server"
         DataSourceId="SqlDataSource1" DataTextField="ProductName"
         DataValueField="ProductID">
    </asp:DropDownList>
    
  5. Speichern Sie Default.aspx, und zeigen Sie sie im Browser an. Beachten Sie, dass dropDownList alle Produkte aus der Northwind-Datenbank enthält.

  6. Schließen Sie den Browser.

  7. Fügen Sie in der Quellansicht von Default.aspx unter dem DropDownList-Steuerelement ein neues TextBox-Steuerelement hinzu. Ändern Sie die ID-Eigenschaft des TextBox-Objekts in txtProductName.

  8. Fügen Sie unter dem TextBox-Steuerelement ein neues Button-Steuerelement hinzu. Ändern Sie die ID-Eigenschaft der Schaltfläche in btnUpdate und die Text-Eigenschaft in Produktname aktualisieren.

  9. Fügen Sie in der Quellansicht von Default.aspx dem SqlDataSource-Tag wie folgt eine UpdateCommand-Eigenschaft und zwei neue UpdateParameters hinzu:

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ConnectionStrings:Northwind%>"
        SelectCommand="SELECT * FROM Products"
        UpdateCommand="UPDATE Products SET ProductName=@ProductName WHERE ProductID=@ProductID">
          <UpdateParameters>
          <asp:ControlParameter Name="ProductName" 
            ControlID="txtProductName" PropertyName="Text" />
          <asp:ControlParameter Name="ProductID" 
            ControlID="ddlProducts" PropertyName="SelectedValue" />
    </asp:SqlDataSource>
    

    Hinweis

    Beachten Sie, dass diesem Code zwei Updateparameter (ProductName und ProductID) hinzugefügt wurden. Diese Parameter werden der Text-Eigenschaft des txtProductName-Textfelds und der SelectedValue-Eigenschaft der DropDownList-Eigenschaft ddlProducts zugeordnet.

  10. Wechseln Sie zur Entwurfsansicht, und doppelklicken Sie auf das Button-Steuerelement, um einen Ereignishandler hinzuzufügen.

  11. Fügen Sie dem btnUpdate_Click Code den folgenden Code hinzu:

    SqlDataSource1.Update();
    
  12. Klicken Sie mit der rechten Maustaste auf Default.aspx, und wählen Sie aus, um es im Browser anzuzeigen. Klicken Sie auf Ja, wenn Sie aufgefordert werden, alle Änderungen zu speichern.

  13. ASP.NET 2.0-Partielle Klassen ermöglichen die Kompilierung zur Laufzeit. Es ist nicht erforderlich, eine Anwendung zu erstellen, damit Codeänderungen wirksam werden.

  14. Wählen Sie ein Produkt aus der DropDownList aus.

  15. Geben Sie im Textfeld einen neuen Namen für das ausgewählte Produkt ein, und klicken Sie dann auf die Schaltfläche Aktualisieren.

  16. Der Produktname wird in der Datenbank aktualisiert.

Übung 3 Verwenden des ObjectDataSource-Steuerelements

In dieser Übung wird veranschaulicht, wie Sie das ObjectDataSource-Steuerelement und ein Quellobjekt für die Interaktion mit der Northwind-Datenbank verwenden.

  1. Klicken Sie mit der rechten Maustaste auf das Projekt in Projektmappen-Explorer, und klicken Sie auf Neues Element hinzufügen.

  2. Wählen Sie in der Vorlagenliste Webformular aus. Ändern Sie den Namen in object.aspx, und klicken Sie auf Hinzufügen.

  3. Klicken Sie mit der rechten Maustaste auf das Projekt in Projektmappen-Explorer, und klicken Sie auf Neues Element hinzufügen.

  4. Wählen Sie in der Vorlagenliste Klasse aus. Ändern Sie den Namen der Klasse in NorthwindData.cs, und klicken Sie auf Hinzufügen.

  5. Klicken Sie auf Ja, wenn Sie aufgefordert werden, die Klasse dem Ordner App_Code hinzuzufügen.

  6. Fügen Sie der Datei NorthwindData.cs 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 System.Data.SqlClient;
    public class NorthwindData {
        private string _connectionString;
        public NorthwindData() {
            Initialize();
        }
    
        private void Initialize() {
            if (ConfigurationManager.ConnectionStrings["Northwind"] == null ||
                ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == "") {
                    throw new Exception("A connection string named 'Northwind' with " +
                    "a valid connection string must exist in the <connectionStrings> " +
                    "configuration section for the application.");
            }
            _connectionString = ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
        }
    
        public DataTable GetAllEmployees(string sortColumns, int startRecord, int maxRecords) {
            VerifySortColumns(sortColumns);
            string sqlCmd = "SELECT EmployeeID, LastName, FirstName, Address, " +
                "City, Region, PostalCode FROM Employees ";
            if (sortColumns.Trim() == "")
                sqlCmd += "ORDER BY EmployeeID";
            else
                sqlCmd += "ORDER BY " + sortColumns;
    
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlDataAdapter da = new SqlDataAdapter(sqlCmd, conn);
            DataSet ds = new DataSet();
            try {
                conn.Open();
                da.Fill(ds, startRecord, maxRecords, "Employees");
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            }
            return ds.Tables["Employees"];
        }
    
        public int SelectCount() {
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM Employees", conn);
            int result = 0;
    
            try {
                conn.Open();
                result = (int)cmd.ExecuteScalar();
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            }
            return result;
        }
    
        //////////
        // Verify that only valid columns are specified in the sort expression to
        // avoid a SQL Injection attack.
        private void VerifySortColumns(string sortColumns) {
            if (sortColumns.ToLowerInvariant().EndsWith(" desc"))
                sortColumns = sortColumns.Substring(0, sortColumns.Length - 5);
            string[] columnNames = sortColumns.Split(',');
            foreach (string columnName in columnNames) {
                switch (columnName.Trim().ToLowerInvariant()) {
                    case "employeeid":
                        break;
                    case "lastname":
                        break;
                    case "firstname":
                        break;
                    case "":
                        break;
                    default:
                        throw new ArgumentException("SortColumns contains an " +
                            "invalid column name.");
                        break;
                }
            }
        }
    
        // Select an employee.
        public DataTable GetEmployee(int EmployeeID) {
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlDataAdapter da =
                new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, " +
                "Address, City, Region, PostalCode " +
                " FROM Employees WHERE EmployeeID = @EmployeeID", conn);
            da.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
            DataSet ds = new DataSet();
            try {
                conn.Open();
                da.Fill(ds, "Employees");
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            }
    
            return ds.Tables["Employees"];
        }
    
        // Delete the Employee by ID.
        public int DeleteEmployee(int EmployeeID) {
             SqlConnection conn = new SqlConnection(_connectionString);
             SqlCommand cmd = new SqlCommand("DELETE FROM Employees WHERE " +
                 "EmployeeID = @EmployeeID", conn);
             cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
             int result = 0;
             try {
                 conn.Open();
                 result = cmd.ExecuteNonQuery();
             } catch (SqlException e) {
                 // Handle exception.
             } finally {
                 conn.Close();
             }
    
             return result;
         }
    
         // Update the Employee by original ID.
         public int UpdateEmployee(int EmployeeID, string LastName, string FirstName,
             string Address, string City, string Region,
             string PostalCode) {
             if (String.IsNullOrEmpty(FirstName))
                 throw new ArgumentException("FirstName cannot be null or an empty string.");
             if (String.IsNullOrEmpty(LastName))
                 throw new ArgumentException("LastName cannot be null or an empty string.");
             if (Address == null) { Address = String.Empty; }
             if (City == null) { City = String.Empty; }
             if (Region == null) { Region = String.Empty; }
             if (PostalCode == null) { PostalCode = String.Empty; }
    
             SqlConnection conn = new SqlConnection(_connectionString);
             SqlCommand cmd = new SqlCommand("UPDATE Employees " +
                 " SET FirstName=@FirstName, " +
                 "LastName=@LastName, " +
                 "Address=@Address, City=@City, " +
                 "Region=@Region, " +
                 "PostalCode=@PostalCode " +
                 "WHERE EmployeeID=@EmployeeID", conn);
             cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;
             cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
             cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
             cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
             cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
             cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
             cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
    
             int result = 0;
             try {
                 conn.Open();
                 result = cmd.ExecuteNonQuery();
             } catch (SqlException e) {
                 // Handle exception.
             } finally {
                 conn.Close();
             }
    
             return result;
        }
    
        // Insert an Employee.
        public int InsertEmployee(string LastName, string FirstName,
            string Address, string City, string Region,
            string PostalCode) {
            if (String.IsNullOrEmpty(FirstName))
                throw new ArgumentException("FirstName cannot be null or an empty string.");
            if (String.IsNullOrEmpty(LastName))
                throw new ArgumentException("LastName cannot be null or an empty string.");
            if (Address == null) { Address = String.Empty; }
            if (City == null) { City = String.Empty; }
            if (Region == null) { Region = String.Empty; }
            if (PostalCode == null) { PostalCode = String.Empty; }
    
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlCommand cmd = new SqlCommand("INSERT INTO Employees " +
                " (FirstName, LastName, Address, " +
                " City, Region, PostalCode) " +
                " Values(@FirstName, @LastName, " +
                "@Address, @City, @Region, @PostalCode); " +
                "SELECT @EmployeeID = SCOPE_IDENTITY()", conn);
    
            cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;
            cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
            cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
            cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
            cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
            cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
            SqlParameter p = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int);
                p.Direction = ParameterDirection.Output;
            int newEmployeeID = 0;
            try {
                conn.Open();
                cmd.ExecuteNonQuery();
                newEmployeeID = (int)p.Value;
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            }
    
            return newEmployeeID;
        }
    
        //
        // Methods that support Optimistic Concurrency checks.
        //
        // Delete the Employee by ID.
        public int DeleteEmployee(int original_EmployeeID, string original_LastName,
            string original_FirstName, string original_Address,
            string original_City, string original_Region,
            string original_PostalCode) {
    
            if (String.IsNullOrEmpty(original_FirstName))
                throw new ArgumentException("FirstName cannot be null or an empty string.");
            if (String.IsNullOrEmpty(original_LastName))
                throw new ArgumentException("LastName cannot be null or an empty string.");
            if (original_Address == null) { original_Address = String.Empty; }
            if (original_City == null) { original_City = String.Empty; }
            if (original_Region == null) { original_Region = String.Empty; }
            if (original_PostalCode == null) { original_PostalCode = String.Empty; }
            string sqlCmd = "DELETE FROM Employees WHERE EmployeeID = " + @original_EmployeeID
    
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlCommand cmd = new SqlCommand(sqlCmd, conn);
            cmd.Parameters.Add("@original_EmployeeID",
                SqlDbType.Int).Value = original_EmployeeID;
            cmd.Parameters.Add("@original_FirstName",
                SqlDbType.VarChar, 10).Value = original_FirstName;
            cmd.Parameters.Add("@original_LastName",
                SqlDbType.VarChar, 20).Value = original_LastName;
            cmd.Parameters.Add("@original_Address",
                SqlDbType.VarChar, 60).Value = original_Address;
            cmd.Parameters.Add("@original_City",
                SqlDbType.VarChar, 15).Value = original_City;
            cmd.Parameters.Add("@original_Region",
                SqlDbType.VarChar, 15).Value = original_Region;
            cmd.Parameters.Add("@original_PostalCode",
                SqlDbType.VarChar, 10).Value = original_PostalCode;
    
            int result = 0;
            try {
                conn.Open();
                result = cmd.ExecuteNonQuery();
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            }
    
            return result;
        }
    
        // Update the Employee by original ID.
        public int UpdateEmployee(string LastName, string FirstName,
            string Address, string City, string Region,
            string PostalCode, int original_EmployeeID,
            string original_LastName, string original_FirstName,
            string original_Address, string original_City,
            string original_Region, string original_PostalCode) {
    
            if (String.IsNullOrEmpty(FirstName))
                throw new ArgumentException("FirstName cannot be null or an empty string.");
            if (String.IsNullOrEmpty(LastName))
                throw new ArgumentException("LastName cannot be null or an empty string.");
            if (Address == null) { Address = String.Empty; }
            if (City == null) { City = String.Empty; }
            if (Region == null) { Region = String.Empty; }
            if (PostalCode == null) { PostalCode = String.Empty; }
            if (original_Address == null) { original_Address = String.Empty; }
            if (original_City == null) { original_City = String.Empty; }
            if (original_Region == null) { original_Region = String.Empty; }
            if (original_PostalCode == null) { original_PostalCode = String.Empty; }
    
            string sqlCmd = "UPDATE Employees " +
                " SET FirstName = @FirstName, LastName = @LastName, " +
                " Address = @Address, City = @City, Region = @Region, " +
                " PostalCode = @PostalCode " +
                " WHERE EmployeeID = @original_EmployeeID";
    
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlCommand cmd = new SqlCommand(sqlCmd, conn);
            cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;
            cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
            cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
            cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
            cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
            cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
            cmd.Parameters.Add("@original_EmployeeID",
                SqlDbType.Int).Value = original_EmployeeID;
            cmd.Parameters.Add("@original_FirstName",
                SqlDbType.VarChar, 10).Value = original_FirstName;
            cmd.Parameters.Add("@original_LastName",
                SqlDbType.VarChar, 20).Value = original_LastName;
            cmd.Parameters.Add("@original_Address",
                SqlDbType.VarChar, 60).Value = original_Address;
            cmd.Parameters.Add("@original_City",
                SqlDbType.VarChar, 15).Value = original_City;
            cmd.Parameters.Add("@original_Region",
                SqlDbType.VarChar, 15).Value = original_Region;
            cmd.Parameters.Add("@original_PostalCode",
                SqlDbType.VarChar, 10).Value = original_PostalCode;
    
            int result = 0;
    
            try {
                conn.Open();
                result = cmd.ExecuteNonQuery();
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            }
            return result;
        }
    }
    
  7. Fügen Sie der Quellansicht von object.aspx den folgenden Code hinzu:

    <%@ Page language="C#" %>
    <script RunAt="server">
    void EmployeesDetailsView_ItemInserted(Object sender, DetailsViewInsertedEventArgs e) {
        EmployeesGridView.DataBind();
    }
    
    void EmployeesDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e) {
        EmployeesGridView.DataBind();
    }
    
    void EmployeesDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e) {
        EmployeesGridView.DataBind();
    }
    void EmployeesGridView_OnSelectedIndexChanged(object sender, EventArgs e) {
        EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue =
            EmployeesGridView.SelectedDataKey.Value.ToString();
        EmployeesDetailsView.DataBind();
    }
    void EmployeeDetailsObjectDataSource_OnInserted(object sender,
        ObjectDataSourceStatusEventArgs e) {
    
        EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue =
            e.ReturnValue.ToString();
        EmployeesDetailsView.DataBind();
    }
    void EmployeeDetailsObjectDataSource_OnUpdated(object sender,
        ObjectDataSourceStatusEventArgs e) {
    
        if ((int)e.ReturnValue == 0)
            Msg.Text = "Employee was not updated. Please try again.";
    }
    void EmployeeDetailsObjectDataSource_OnDeleted(object sender,
        ObjectDataSourceStatusEventArgs e) {
    
        if ((int)e.ReturnValue == 0)
            Msg.Text = "Employee was not deleted. Please try again.";
    }
    void Page_Load() {
        Msg.Text = "";
    }
    </script>
    <html>
      <body>
        <form id="Form1" runat="server">
          <h3>ObjectDataSource Example</h3>
          <asp:Label id="Msg" runat="server" ForeColor="Red" />
          <asp:ObjectDataSource
              ID="EmployeesObjectDataSource"
              runat="server"
              TypeName="NorthwindData"
              SortParameterName="SortColumns"
              EnablePaging="true"
              SelectCountMethod="SelectCount"
              StartRowIndexParameterName="StartRecord"
              MaximumRowsParameterName="MaxRecords"
              SelectMethod="GetAllEmployees" >
          </asp:ObjectDataSource>
          <asp:ObjectDataSource
              ID="EmployeeDetailsObjectDataSource"
              runat="server"
              TypeName="NorthwindData"
              ConflictDetection="CompareAllValues"
              OldValuesParameterFormatString="{0}"
              SelectMethod="GetEmployee"
              InsertMethod="InsertEmployee"
              UpdateMethod="UpdateEmployee"
              DeleteMethod="DeleteEmployee"
              OnInserted="EmployeeDetailsObjectDataSource_OnInserted"
              OnUpdated="EmployeeDetailsObjectDataSource_OnUpdated"
              OnDeleted="EmployeeDetailsObjectDataSource_OnDeleted">
              <SelectParameters>
                  <asp:Parameter Name="EmployeeID" Type="Int32" />
              </SelectParameters>
          </asp:ObjectDataSource>
          <table cellspacing="10">
            <tr>
              <td valign="top">
                <asp:GridView ID="EmployeesGridView"
                    DataSourceID="EmployeesObjectDataSource"
                    AutoGenerateColumns="false"
                    AllowSorting="true"
                    AllowPaging="true"
                    PageSize="5"
                    DataKeyNames="EmployeeID"
                    OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
                    RunAt="server">
                    <HeaderStyle backcolor="lightblue" forecolor="black"/>
                    <Columns>
                    <asp:ButtonField Text="Details..."
                    HeaderText="Show Details"
                    CommandName="Select"/>
    
                    <asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"
                    SortExpression="EmployeeID" />
                    <asp:BoundField DataField="FirstName" HeaderText="First Name"
                    SortExpression="FirstName" />
                    <asp:BoundField DataField="LastName" HeaderText="Last Name"
                    SortExpression="LastName, FirstName" />
                    </Columns>
                </asp:GridView>
              </td>
              <td valign="top">
                <asp:DetailsView ID="EmployeesDetailsView"
                    DataSourceID="EmployeeDetailsObjectDataSource"
                    AutoGenerateRows="false"
                    EmptyDataText="No records."
                    DataKeyNames="EmployeeID"
                    Gridlines="Both"
                    AutoGenerateInsertButton="true"
                    AutoGenerateEditButton="true"
                    AutoGenerateDeleteButton="true"
                    OnItemInserted="EmployeesDetailsView_ItemInserted"
                    OnItemUpdated="EmployeesDetailsView_ItemUpdated"
                    OnItemDeleted="EmployeesDetailsView_ItemDeleted"
                    RunAt="server">
                    <HeaderStyle backcolor="Navy" forecolor="White"/>
                    <RowStyle backcolor="White"/>
                    <AlternatingRowStyle backcolor="LightGray"/>
                    <EditRowStyle backcolor="LightCyan"/>
                    <Fields>
                        <asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"
                            InsertVisible="False" ReadOnly="true"/>
                        <asp:BoundField DataField="FirstName" HeaderText="First Name"/>
                        <asp:BoundField DataField="LastName" HeaderText="Last Name"/>
                        <asp:BoundField DataField="Address" HeaderText="Address"/>
                        <asp:BoundField DataField="City" HeaderText="City"/>
                        <asp:BoundField DataField="Region" HeaderText="Region"/>
                        <asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>
                    </Fields>
                  </asp:DetailsView>
                </td>
              </tr>
            </table>
          </form>
        </body>
      </html>
    
  8. Speichern Sie alle Dateien, und durchsuchen Sie object.aspx.

  9. Interagieren Sie mit der Benutzeroberfläche, indem Sie Details anzeigen, Mitarbeiter bearbeiten, Mitarbeiter hinzufügen und Mitarbeiter löschen.