Freigeben über


Konfigurieren von Einstellungen der Datenzugriffsschicht auf Verbindungs- und Befehlsebene (C#)

von Scott Mitchell

PDF herunterladen

Die TableAdapters in einem typierten DataSet kümmern sich automatisch um das Herstellen einer Verbindung mit der Datenbank, das Ausgeben von Befehlen und das Auffüllen einer DataTable mit den Ergebnissen. Es gibt jedoch Gelegenheiten, in denen wir uns um diese Details kümmern möchten, und in diesem Lernprogramm erfahren Wir, wie Sie auf die Einstellungen für die Datenbankverbindung und die Befehlsebene im TableAdapter zugreifen können.

Einleitung

In der gesamten Lernprogrammreihe haben wir Typed DataSets verwendet, um die Datenzugriffsschicht und Geschäftsobjekte unserer mehrschichtigen Architektur zu implementieren. Wie im ersten Lernprogramm erläutert, dienen die DataTables der Typed DataSets als Speicher für Daten, während die TableAdapters als Wrapper fungieren, die mit der Datenbank kommunizieren, um die zugrunde liegenden Daten abzurufen und zu ändern. Die TableAdapters kapseln die Komplexität der Arbeit mit der Datenbank und ersparen es uns, Code zu schreiben, um eine Verbindung zur Datenbank herzustellen, einen Befehl auszuführen oder die Ergebnisse in eine Datentabelle zu schreiben.

Es gibt jedoch Zeiten, in denen wir in die Tiefen des TableAdapters eingraben und Code schreiben müssen, der direkt mit den ADO.NET-Objekten funktioniert. Im Lernprogramm zum Umschließen von Datenbankänderungen in einer Transaktion haben wir dem TableAdapter Methoden hinzugefügt, um ADO.NET Transaktionen zu beginnen, zu committen und zurückzusetzen. Diese Methoden haben ein internes, manuell erstelltes SqlTransaction Objekt verwendet, das den TableAdapter-Objekten SqlCommand zugewiesen wurde.

In diesem Lernprogramm untersuchen wir, wie Sie auf die Einstellungen für die Datenbankverbindung und die Befehlsebene im TableAdapter zugreifen. Insbesondere fügen wir Funktionen hinzu, die den Zugriff auf ProductsTableAdapter ermöglichen, um die zugrunde liegenden Verbindungszeichenfolgen und Befehlstimeout-Einstellungen zu steuern.

Arbeiten mit Daten mithilfe von ADO.NET

Das Microsoft .NET Framework enthält eine Vielzahl von Klassen, die speziell für die Arbeit mit Daten entwickelt wurden. Diese Klassen, die sich im System.Data Namespace befinden, werden als die ADO.NET Klassen bezeichnet. Einige der Klassen unter dem ADO.NET Dach sind an einen bestimmten Datenanbieter gebunden. Sie können sich einen Datenanbieter als Kommunikationskanal vorstellen, mit dem Informationen zwischen den ADO.NET Klassen und dem zugrunde liegenden Datenspeicher fließen können. Es gibt generalisierte Anbieter wie OleDb und ODBC sowie Anbieter, die speziell für ein bestimmtes Datenbanksystem entwickelt wurden. Beispielsweise ist es möglich, eine Verbindung mit einer Microsoft SQL Server-Datenbank mithilfe des OleDb-Anbieters herzustellen, der SqlClient-Anbieter ist wesentlich effizienter, da er speziell für SQL Server entwickelt und optimiert wurde.

Beim programmgesteuerten Zugriff auf Daten wird das folgende Muster häufig verwendet:

  • Stellen Sie eine Verbindung mit der Datenbank her.
  • Ausgeben eines Befehls.
  • Arbeiten Sie bei SELECT Abfragen mit den resultierenden Datensätzen.

Es gibt separate ADO.NET Klassen zum Ausführen jeder dieser Schritte. Verwenden Sie z. B. die SqlConnection Klasse, um eine Verbindung mit einer Datenbank mithilfe des SqlClient-Anbieters herzustellen. Um einen INSERT, UPDATE, DELETE oder SELECT Befehl an die Datenbank auszustellen, verwenden Sie die SqlCommand Klasse.

Mit Ausnahme des Tutorials Einhüllen von Datenbankänderungen in eine Transaktion mussten wir keinen ADO.NET Low-Level-Code selbst schreiben, da der automatisch generierte Code der TableAdapters die Funktionalität enthält, die benötigt wird, um eine Verbindung mit der Datenbank herzustellen, Befehle auszuführen, Daten abzurufen und diese Daten in DataTables zu füllen. Es kann jedoch vorkommen, dass wir diese Einstellungen auf niedriger Ebene anpassen müssen. In den nächsten Schritten werden wir untersuchen, wie Sie auf die ADO.NET-Objekte zugreifen können, die intern von den TableAdapters verwendet werden.

Schritt 1: Untersuchen mit der Connection-Eigenschaft

Jede TableAdapter-Klasse verfügt über eine Connection Eigenschaft, die Datenbankverbindungsinformationen angibt. Der Datentyp und ConnectionString der Wert dieser Eigenschaft werden durch die Im TableAdapter-Konfigurations-Assistenten getroffenen Auswahlen bestimmt. Denken Sie daran, dass wir, wenn wir zum ersten Mal einen TableAdapter zu einem typisierten DataSet hinzufügen, von diesem Assistenten nach der Datenbankquelle gefragt werden (siehe Abbildung 1). Die Auswahlliste in diesem ersten Schritt enthält die in der Konfigurationsdatei angegebenen Datenbanken sowie alle anderen Datenbanken in den Datenverbindungen im Server-Explorer. Wenn die datenbank, die wir verwenden möchten, in der Dropdownliste nicht vorhanden ist, kann eine neue Datenbankverbindung angegeben werden, indem Sie auf die Schaltfläche "Neue Verbindung" klicken und die erforderlichen Verbindungsinformationen angeben.

Der erste Schritt des TableAdapter-Konfigurations-Assistenten

Abbildung 1: Der erste Schritt des TableAdapter-Konfigurations-Assistenten (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Nehmen wir uns einen Moment Zeit, um den Code für die TableAdapter s-Eigenschaft Connection zu untersuchen. Wie im Lernprogramm zum Erstellen einer Datenzugriffsschicht erwähnt, können wir den automatisch generierten TableAdapter-Code anzeigen, indem wir zum Fenster "Klassenansicht" wechseln, einen Drilldown zur entsprechenden Klasse ausführen und dann auf den Membernamen doppelklicken.

Navigieren Sie zum Fenster "Klassenansicht", indem Sie zum Menü "Ansicht" wechseln und "Klassenansicht" auswählen (oder STRG+UMSCHALT+C eingeben). Führen Sie in der oberen Hälfte des Fensters "Klassenansicht" einen Drilldown zum NorthwindTableAdapters Namespace durch, und wählen Sie die ProductsTableAdapter Klasse aus. Dadurch werden die ProductsTableAdapter Mitglieder in der unteren Hälfte der Klassenansicht angezeigt, wie in Abbildung 2 dargestellt. Doppelklicken Sie auf die Connection Eigenschaft, um den zugehörigen Code anzuzeigen.

Double-Click die Verbindungseigenschaft in der Klassenansicht, um ihren automatisch generierten Code anzuzeigen

Abbildung 2: Double-Click die Verbindungseigenschaft in der Klassenansicht, um den automatisch generierten Code anzuzeigen

Die Eigenschaft Connection des TableAdapters sowie anderer verbindungsbezogener Code folgt:

private System.Data.SqlClient.SqlConnection _connection;
private void InitConnection() {
    this._connection = new System.Data.SqlClient.SqlConnection();
    this._connection.ConnectionString = 
        ConfigurationManager.ConnectionStrings["NORTHWNDConnectionString"].ConnectionString;
}
internal System.Data.SqlClient.SqlConnection Connection {
    get {
        if ((this._connection == null)) {
            this.InitConnection();
        }
        return this._connection;
    }
    set {
        this._connection = value;
        if ((this.Adapter.InsertCommand != null)) {
            this.Adapter.InsertCommand.Connection = value;
        }
        if ((this.Adapter.DeleteCommand != null)) {
            this.Adapter.DeleteCommand.Connection = value;
        }
        if ((this.Adapter.UpdateCommand != null)) {
            this.Adapter.UpdateCommand.Connection = value;
        }
        for (int i = 0; (i < this.CommandCollection.Length); i = (i + 1)) {
            if ((this.CommandCollection[i] != null)) {
                ((System.Data.SqlClient.SqlCommand)
                    (this.CommandCollection[i])).Connection = value;
            }
        }
    }
}

Wenn die TableAdapter-Klasse instanziiert wird, ist die Membervariable _connection gleich null. Wenn auf die Connection Eigenschaft zugegriffen wird, überprüft sie zunächst, ob die _connection Membervariable instanziiert wurde. Falls nicht, wird die InitConnection Methode aufgerufen, die _connection instanziiert und ihre ConnectionString Eigenschaft auf den im ersten Schritt des TableAdapter-Konfigurations-Assistenten angegebenen Verbindungszeichenfolgenwert festlegt.

Die Connection Eigenschaft kann auch einem SqlConnection Objekt zugewiesen werden. Dadurch wird das neue SqlConnection Objekt den einzelnen TableAdapter-Objekten SqlCommand zugeordnet.

Schritt 2: Verfügbarmachen von Connection-Level Einstellungen

Die Verbindungsinformationen sollten innerhalb des TableAdapters gekapselt bleiben und für andere Ebenen in der Anwendungsarchitektur nicht zugänglich sein. Es kann jedoch Szenarien geben, in dem informationen auf Verbindungsebene von TableAdapter für eine Abfrage, einen Benutzer oder eine ASP.NET Seite zugänglich oder angepasst werden müssen.

Wir sollten das ProductsTableAdapter im Northwind DataSet erweitern, um eine ConnectionString Eigenschaft zu integrieren, die von der Geschäftslogikebene genutzt werden kann, um die Verbindungszeichenfolge des TableAdapters zu lesen oder zu ändern.

Hinweis

Eine Verbindungszeichenfolge ist eine Zeichenfolge, die Datenbankverbindungsinformationen angibt, z. B. den zu verwendenden Anbieter, den Speicherort der Datenbank, Authentifizierungsanmeldeinformationen und andere datenbankbezogene Einstellungen. Eine Liste der Verbindungszeichenfolgenmuster, die von einer Vielzahl von Datenspeichern und Anbietern verwendet werden, finden Sie unter ConnectionStrings.com.

Wie im Lernprogramm zum Erstellen einer Datenzugriffsebene erläutert, können die automatisch generierten Typed DataSet-Klassen über die Verwendung partieller Klassen erweitert werden. Erstellen Sie zunächst einen neuen Unterordner im Projekt mit dem Namen ConnectionAndCommandSettings, der sich unter dem Ordner ~/App_Code/DAL befindet.

Hinzufügen eines Unterordners namens

Abbildung 3: Hinzufügen eines Unterordners mit dem Namen ConnectionAndCommandSettings

Fügen Sie eine neue Klassendatei mit dem Namen hinzu ProductsTableAdapter.ConnectionAndCommandSettings.cs , und geben Sie den folgenden Code ein:

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;
namespace NorthwindTableAdapters
{
    public partial class ProductsTableAdapter
    {
        public string ConnectionString
        {
            get
            {
                return this.Connection.ConnectionString;
            }
            set
            {
                this.Connection.ConnectionString = value;
            }
        }
    }
}

Diese partielle Klasse fügt der Klasse public eine Eigenschaft ConnectionString mit dem Namen ProductsTableAdapter hinzu, die es jeder Ebene ermöglicht, die Verbindungszeichenfolge für die zugrunde liegende Verbindung des TableAdapter zu lesen oder zu aktualisieren.

Öffnen Sie die ProductsBLL Klasse, nachdem Sie diese partielle Klasse erstellt (und gespeichert) haben. Wechseln Sie zu einer der vorhandenen Methoden und geben Sie Adapter ein. Drücken Sie dann die Punkt-Taste, um IntelliSense aufzurufen. Die neue ConnectionString Eigenschaft sollte in IntelliSense verfügbar sein, d. h., Sie können diesen Wert programmgesteuert aus der BLL lesen oder anpassen.

Verfügbarmachen des gesamten Verbindungsobjekts

Diese partielle Klasse macht nur eine Eigenschaft des zugrunde liegenden Verbindungsobjekts verfügbar: ConnectionString. Wenn Sie das gesamte Verbindungsobjekt über die Grenzen des TableAdapter hinaus verfügbar machen möchten, können Sie alternativ die Schutzebene der Connection Eigenschaft ändern. Der in Schritt 1 untersuchte automatisch generierte Code hat gezeigt, dass die TableAdapter-Eigenschaft Connection als internalgekennzeichnet ist, was bedeutet, dass nur von Klassen in derselben Assembly darauf zugegriffen werden kann. Dies kann jedoch über die TableAdapter-Eigenschaft ConnectionModifier geändert werden.

Öffnen Sie das Northwind DataSet, klicken Sie auf den ProductsTableAdapter Designer, und navigieren Sie zum Eigenschaftenfenster. Dort wird der ConnectionModifier Wert auf den Standardwert festgelegt. Assembly Um die Connection Eigenschaft außerhalb der Typed DataSet-Assembly verfügbar zu machen, ändern Sie die ConnectionModifier Eigenschaft in Public.

Die Barrierefreiheitsstufe der Verbindungseigenschaft kann über die ConnectionModifier-Eigenschaft konfiguriert werden.

Abbildung 4: Die Connection Barrierefreiheitsstufe der Eigenschaft kann über die ConnectionModifier Eigenschaft konfiguriert werden (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Speichern Sie das DataSet, und kehren Sie dann zur ProductsBLL Klasse zurück. Wechseln Sie wie zuvor zu einer der vorhandenen Methoden, geben Sie Adapter ein, und drücken Sie dann die Punkt-Taste, um IntelliSense aufzurufen. Die Liste sollte eine Connection Eigenschaft enthalten, was bedeutet, dass Sie jetzt programmgesteuert alle Einstellungen auf Verbindungsebene aus der BLL lesen oder zuweisen können.

Ein TableAdapter besteht aus einer Hauptabfrage, die standardmäßig automatisch generierte INSERT, UPDATEund DELETE Anweisungen enthält. Diese Hauptabfragen INSERT, UPDATE und DELETE-Anweisungen werden im Code des TableAdapters als ADO.NET-Datenadapterobjekt über die Adapter-Eigenschaft implementiert. Wie bei der Connection Eigenschaft wird der Datentyp der Adapter Eigenschaft vom verwendeten Datenanbieter bestimmt. Da diese Lernprogramme den SqlClient-Anbieter verwenden, ist die Adapter Eigenschaft vom Typ SqlDataAdapter.

Die TableAdapter-Eigenschaft Adapter weist drei Eigenschaften vom Typ SqlCommand auf, die zum Ausgeben der INSERT, UPDATEund DELETE Anweisungen verwendet werden:

  • InsertCommand
  • UpdateCommand
  • DeleteCommand

Ein SqlCommand Objekt ist für das Senden einer bestimmten Abfrage an die Datenbank verantwortlich und verfügt über Eigenschaften wie: CommandText, die die ad-hoc SQL-Anweisung oder gespeicherte Prozedur enthält, die ausgeführt werden soll; und Parametersdies ist eine Sammlung von SqlParameter Objekten. Wie wir im Lernprogramm zum Erstellen einer Datenzugriffsebene gesehen haben, können diese Befehlsobjekte über das Eigenschaftenfenster angepasst werden.

Zusätzlich zur Hauptabfrage kann das TableAdapter eine variable Anzahl von Methoden enthalten, die beim Aufrufen einen angegebenen Befehl an die Datenbank verteilen. Das Befehlsobjekt der Hauptabfrage und die Befehlsobjekte für alle zusätzlichen Methoden werden in der TableAdapter-Eigenschaft CommandCollection gespeichert.

Nehmen wir uns einen Moment Zeit, um den Code zu betrachten, der im DataSet von ProductsTableAdapter und Northwind für diese beiden Eigenschaften und deren unterstützende Membervariablen und Hilfsmethoden generiert wird.

private System.Data.SqlClient.SqlDataAdapter _adapter;
private void InitAdapter() {
    this._adapter = new System.Data.SqlClient.SqlDataAdapter();
    
    ... Code that creates the InsertCommand, UpdateCommand, ...
    ... and DeleteCommand instances - omitted for brevity ...
}
private System.Data.SqlClient.SqlDataAdapter Adapter {
    get {
        if ((this._adapter == null)) {
            this.InitAdapter();
        }
        return this._adapter;
    }
}
private System.Data.SqlClient.SqlCommand[] _commandCollection;
private void InitCommandCollection() {
    this._commandCollection = new System.Data.SqlClient.SqlCommand[9];
    ... Code that creates the command objects for the main query and the ...
    ... ProductsTableAdapter�s other eight methods - omitted for brevity ...
}
protected System.Data.SqlClient.SqlCommand[] CommandCollection {
    get {
        if ((this._commandCollection == null)) {
            this.InitCommandCollection();
        }
        return this._commandCollection;
    }
}

Der Code für die Adapter und CommandCollection Eigenschaften ahmt den der Connection Eigenschaft genau nach. Es gibt Membervariablen, die die von den Eigenschaften verwendeten Objekte enthalten. Die Eigenschaften-Accessoren get überprüfen zunächst, ob die entsprechende Mitgliedsvariable null ist. In diesem Fall wird eine Initialisierungsmethode aufgerufen, die eine Instanz der Membervariable erstellt und die kernbefehlsbezogenen Eigenschaften zuweist.

Schritt 4: Verfügbarmachen von Command-Level Einstellungen

Im Idealfall sollten die Informationen auf Befehlsebene innerhalb der Datenzugriffsschicht gekapselt bleiben. Sollten diese Informationen in anderen Ebenen der Architektur benötigt werden, kann sie jedoch über eine partielle Klasse verfügbar gemacht werden, genau wie bei den Einstellungen auf Verbindungsebene.

Da "TableAdapter" nur über eine einzelne Connection Eigenschaft verfügt, ist der Code zum Verfügbarmachen von Einstellungen auf Verbindungsebene relativ einfach. Die Dinge sind etwas komplizierter, wenn Sie Einstellungen auf Befehlsebene ändern, da das TableAdapter mehrere Befehlsobjekte aufweisen kann – ein InsertCommand, UpdateCommandund , und DeleteCommand, zusammen mit einer variablen Anzahl von Befehlsobjekten in der CommandCollection Eigenschaft. Beim Aktualisieren von Einstellungen auf Befehlsebene müssen diese Einstellungen an alle Befehlsobjekte weitergegeben werden.

Stellen Sie sich beispielsweise vor, dass es bestimmte Abfragen im TableAdapter gab, die eine außerordentlich lange Zeit für die Ausführung benötigten. Wenn Sie den TableAdapter zum Ausführen einer dieser Abfragen verwenden, möchten wir möglicherweise die Eigenschaft des Befehlsobjekts CommandTimeouterhöhen. Diese Eigenschaft gibt die Anzahl der Sekunden an, die auf die Ausführung des Befehls warten und standardmäßig 30 ist.

Damit die CommandTimeout Eigenschaft von der BLL angepasst werden kann, fügen Sie die folgende public Methode in die ProductsDataTable ein, wobei Sie die in Schritt 2 erstellte partielle Klassendatei (ProductsTableAdapter.ConnectionAndCommandSettings.cs) nutzen.

public void SetCommandTimeout(int timeout)
{
    if (this.Adapter.InsertCommand != null)
        this.Adapter.InsertCommand.CommandTimeout = timeout;
    if (this.Adapter.DeleteCommand != null)
        this.Adapter.DeleteCommand.CommandTimeout = timeout;
    if (this.Adapter.UpdateCommand != null)
        this.Adapter.UpdateCommand.CommandTimeout = timeout;
    for (int i = 0; i < this.CommandCollection.Length; i++)
        if (this.CommandCollection[i] != null)
            this.CommandCollection[i].CommandTimeout = timeout;
}

Diese Methode kann von der BLL oder Presentation Layer aufgerufen werden, um das Befehlstimeout für alle Befehle von dieser TableAdapter-Instanz festzulegen.

Hinweis

Die Eigenschaften Adapter und CommandCollection sind als private markiert, was bedeutet, dass sie nur durch Code innerhalb des TableAdapters zugänglich sind. Im Gegensatz zur Connection Eigenschaft sind diese Zugriffsmodifizierer nicht konfigurierbar. Wenn Sie daher Eigenschaften auf Befehlsebene für andere Ebenen in der Architektur verfügbar machen müssen, müssen Sie den oben beschriebenen partiellen Klassenansatz verwenden, um eine public Methode oder Eigenschaft bereitzustellen, die die private Befehlsobjekte liest oder schreibt.

Zusammenfassung

Die TableAdapters innerhalb eines typisierten Datensatzes dienen zur Kapselung von Details und Komplexität beim Datenzugriff. Mithilfe von TableAdapters müssen wir uns keine Gedanken machen, ADO.NET Code zum Herstellen einer Verbindung mit der Datenbank zu schreiben, einen Befehl ausstellen oder die Ergebnisse in eine DataTable auffüllen. Es wird alles automatisch für uns gehandhabt.

Es kann jedoch vorkommen, dass wir die ADO.NET-Spezifika auf niedriger Ebene anpassen müssen, z. B. das Ändern der Verbindungszeichenfolge oder der Standardverbindungs- oder Befehlstimeoutwerte. Der TableAdapter verfügt über automatisch generierte Connection, Adapterund CommandCollection Eigenschaften, diese sind jedoch entweder internal oder private, standardmäßig. Diese internen Informationen können verfügbar gemacht werden, indem der TableAdapter mithilfe partieller Klassen erweitert wird, um public Methoden oder Eigenschaften einzuschließen. Alternativ kann die Zugriffmodifikator-Eigenschaft Connection des TableAdapters über die Eigenschaft ConnectionModifier des TableAdapters konfiguriert werden.

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 Burnadette Leigh, S ren Jacob Lauritsen, Teresa Murphy und Hilton Geisenow. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn dies der Fall ist, schreiben Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.