Freigeben über


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

von Scott Mitchell

PDF herunterladen

Die TableAdapters in einem typisierten DataSet kümmern sich automatisch um die Verbindung mit der Datenbank, die Ausgabe von Befehlen und das Auffüllen einer DataTable mit den Ergebnissen. Es gibt jedoch Fälle, in denen wir uns um diese Details selbst kümmern möchten, und in diesem Tutorial erfahren wir, wie Sie auf die Datenbankverbindungs- und Befehlsebeneneinstellungen im TableAdapter zugreifen.

Einführung

In der Tutorialreihe haben wir typisierte DataSets verwendet, um die Datenzugriffsebene und Geschäftsobjekte unserer mehrschichtigen Architektur zu implementieren. Wie im ersten Tutorial erläutert, dienen die DataTables für typisierte DataSets als Repositorys für Daten, während die TableAdapters als Wrapper fungieren, um mit der Datenbank zu kommunizieren, um die zugrunde liegenden Daten abzurufen und zu ändern. TableAdapters kapselt die Komplexität der Arbeit mit der Datenbank und erspart uns das Schreiben von Code, um eine Verbindung mit der Datenbank herzustellen, einen Befehl auszugeben oder die Ergebnisse in eine DataTable aufzufüllen.

Es gibt jedoch Zeiten, in denen wir uns in die Tiefen des TableAdapters eingraben und Code schreiben müssen, der direkt mit den ADO.NET-Objekten funktioniert. Im Tutorial Umschließen von Datenbankänderungen in einer Transaktion haben wir dem TableAdapter beispielsweise Methoden zum Starten, Commiten und Rollback ADO.NET Transaktionen hinzugefügt. Diese Methoden verwendeten ein internes, manuell erstelltes SqlTransaction Objekt, das den TableAdapter-Objekten SqlCommand zugewiesen wurde.

In diesem Tutorial wird der Zugriff auf die Datenbankverbindungs- und Befehlseinstellungen im TableAdapter untersucht. Insbesondere werden wir Funktionen hinzufügen, die den ProductsTableAdapter Zugriff auf die zugrunde liegenden Verbindungszeichenfolge- und Befehlstimeouteinstellungen ermöglicht.

Arbeiten mit Daten mithilfe von ADO.NET

Die Microsoft .NET Framework enthält eine Vielzahl von Klassen, die speziell für die Arbeit mit Daten entwickelt wurden. Diese Klassen, die System.Datasich im Namespace befinden, werden als 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. Während es beispielsweise möglich ist, eine Verbindung mit einer Microsoft SQL Server-Datenbank mithilfe des OleDb-Anbieters herzustellen, ist der SqlClient-Anbieter viel effizienter, da er speziell für SQL Server entwickelt und optimiert wurde.

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

  • Stellen Sie eine Verbindung mit der Datenbank her.
  • Geben Sie einen Befehl aus.
  • Arbeiten Sie SELECT bei Abfragen mit den resultierenden Datensätzen.

Es gibt separate ADO.NET Klassen für die Ausführung jeder dieser Schritte. Verwenden Sie beispielsweise die -Klasse, um mithilfe des SqlClient-Anbieters SqlConnectioneine Verbindung mit einer Datenbank herzustellen. Verwenden Sie die -Klasse, um einen INSERT- UPDATE, DELETE- oder SELECT -Befehl für die SqlCommandDatenbank ausstellen zu können.

Mit Ausnahme des Tutorials Zum Umschließen von Datenbankänderungen in einer Transaktion mussten wir keinen Code auf niedriger Ebene schreiben ADO.NET selbst, da der automatisch generierte TableAdapters-Code die Funktionen enthält, die zum Herstellen einer Verbindung mit der Datenbank, zum Ausgeben von Befehlen, zum Abrufen von Daten und zum Auffüllen dieser Daten in DataTables erforderlich sind. Es kann jedoch vorkommen, dass wir diese Einstellungen auf niedriger Ebene anpassen müssen. In den nächsten Schritten wird untersucht, wie Sie die ADO.NET Objekte nutzen, die intern von 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 vorgenommenen Auswahlen bestimmt. Denken Sie daran, dass wir beim ersten Hinzufügen eines TableAdapter zu einem typisierten DataSet vom Assistenten nach der Datenbankquelle gefragt werden (siehe Abbildung 1). Die Dropdownliste in diesem ersten Schritt enthält die in der Konfigurationsdatei angegebenen Datenbanken sowie alle anderen Datenbanken im Connections des Servers Explorer s Data Connections. Wenn die zu verwendende Datenbank 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-Eigenschaft Connection zu überprüfen. Wie im Tutorial Erstellen einer Datenzugriffsebene beschrieben, können Sie den automatisch generierten TableAdapter-Code anzeigen, indem Sie zum Fenster Klassenansicht wechseln, einen Drilldown zur entsprechenden Klasse durchfü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 aus, und wählen Sie die ProductsTableAdapter Klasse aus. Dadurch werden die ProductsTableAdapter s-Elemente in der unteren Hälfte der Klassenansicht angezeigt, wie in Abbildung 2 dargestellt. Doppelklicken Sie auf die Eigenschaft, um ihren Connection Code anzuzeigen.

Doppelklicken Sie in der Klassenansicht auf die Verbindungseigenschaft, um den automatisch generierten Code anzuzeigen.

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

Die TableAdapter-Eigenschaft Connection und anderer verbindungsbezogener Code folgen:

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, wird zuerst überprüft, ob die _connection Membervariable instanziiert wurde. Andernfalls wird die InitConnection -Methode aufgerufen, die ihre ConnectionString Eigenschaft instanziiert _connection und auf den Verbindungszeichenfolge Wert festlegt, der im ersten Schritt des TableAdapter-Konfigurations-Assistenten angegeben wurde.

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

Schritt 2: Verfügbarmachen Connection-Level Einstellungen

Die Verbindungsinformationen sollten im TableAdapter gekapselt bleiben und nicht für andere Ebenen in der Anwendungsarchitektur zugänglich sein. Es kann jedoch Szenarien geben, in denen die Informationen des TableAdapter-Verbindungsadapters für eine Abfrage, einen Benutzer oder eine ASP.NET Seite zugänglich oder anpassbar sein müssen.

Erweitern ProductsTableAdapter sie im Northwind DataSet um eine ConnectionString Eigenschaft, die von der Geschäftslogikebene zum Lesen oder Ändern der vom TableAdapter verwendeten Verbindungszeichenfolge verwendet werden kann.

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 Verbindungszeichenfolge Muster, die von einer Vielzahl von Datenspeichern und Anbietern verwendet werden, finden Sie unter ConnectionStrings.com.

Wie im Tutorial Erstellen einer Datenzugriffsebene erläutert, können die automatisch generierten Klassen des typisierten DataSets durch die Verwendung partieller Klassen erweitert werden. Erstellen Sie zunächst einen neuen Unterordner im Projekt namens ConnectionAndCommandSettings unter dem ~/App_Code/DAL Ordner.

Hinzufügen eines Unterordners namens ConnectionAndCommandSettings

Abbildung 3: Hinzufügen eines Unterordners namens ConnectionAndCommandSettings

Fügen Sie eine neue Klassendatei namens 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 ProductsTableAdapter -Klasse eine public Eigenschaft mit dem Namen ConnectionString hinzu, die es jeder Ebene ermöglicht, die Verbindungszeichenfolge für die zugrunde liegende TableAdapter-Verbindung zu lesen oder zu aktualisieren.

Öffnen Sie die ProductsBLL Klasse, indem Sie diese partielle Klasse erstellt (und gespeichert haben). Wechseln Sie zu einer der vorhandenen Methoden, geben Sie ein Adapter , und drücken Sie dann den Punktschlüssel, um IntelliSense anzuzeigen. Die neue ConnectionString Eigenschaft sollte in IntelliSense verfügbar sein, was bedeutet, dass Sie diesen Wert programmgesteuert aus der BLL lesen oder anpassen können.

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 automatisch generierte Code, den wir in Schritt 1 untersucht haben, hat gezeigt, dass die TableAdapter-Eigenschaft Connection als internalgekennzeichnet ist, was bedeutet, dass nur Klassen in derselben Assembly darauf zugreifen können. Dies kann jedoch über die TableAdapter-Eigenschaft ConnectionModifier geändert werden.

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

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

Abbildung 4: Die Connection Barrierefreiheitsebene der Eigenschaft kann über die ConnectionModifier Eigenschaft konfiguriert werden (Klicken Sie, 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 ein Adapter , und drücken Sie dann den Punktschlüssel, um IntelliSense zu öffnen. Die Liste sollte eine Connection Eigenschaft enthalten, was bedeutet, dass Sie jetzt alle Einstellungen auf Verbindungsebene programmgesteuert lesen oder aus der BLL zuweisen können.

Ein TableAdapter besteht aus einer Standard Abfrage, die standardmäßig über automatisch generierte INSERT, , UPDATEund DELETE -Anweisungen verfügt. Dies Standard Abfrageanweisungen INSERT, UPDATE, und DELETE 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 Tutorials den SqlClient-Anbieter verwenden, ist die Adapter -Eigenschaft vom Typ SqlDataAdapter.

Die TableAdapter-Eigenschaft Adapter verfügt über drei Eigenschaften vom Typ SqlCommand , die zum Ausgeben der INSERTAnweisungen , UPDATEund DELETE 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 auszuführende Ad-hoc-SQL-Anweisung oder die gespeicherte Prozedur enthält; und Parameters, die eine Auflistung von SqlParameter -Objekten ist. Wie wir im Tutorial Erstellen einer Datenzugriffsebene gezeigt haben, können diese Befehlsobjekte über die Eigenschaftenfenster angepasst werden.

Zusätzlich zur Standard Abfrage kann der TableAdapter eine variable Anzahl von Methoden enthalten, die beim Aufrufen einen angegebenen Befehl an die Datenbank senden. Das Standard Abfrageobjekt des Befehlsobjekts 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 von Northwind im ProductsTableAdapter DataSet für diese beiden Eigenschaften generiert wird, und ihre unterstützenden Membervariablen und Hilfsmethoden:

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 -Eigenschaft imitiert genau den der Connection -Eigenschaft. Es gibt Membervariablen, die die von den Eigenschaften verwendeten Objekte enthalten. Die Eigenschaften-Accessoren get überprüfen zunächst, ob die entsprechende Membervariable ist null. In diesem Zusammenhang wird eine Initialisierungsmethode aufgerufen, die eine instance der Membervariable erstellt und die hauptbefehlsbezogenen Eigenschaften zuweist.

Schritt 4: Verfügbarmachen Command-Level Einstellungen

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

Da tableAdapter nur über eine einzelne Connection Eigenschaft verfügt, ist der Code zum Verfügbarmachen von Einstellungen auf Verbindungsebene recht einfach. Beim Ändern von Einstellungen auf Befehlsebene sind die Dinge etwas komplizierter, da der TableAdapter mehrere Befehlsobjekte aufweisen kann – ein InsertCommand, UpdateCommandund , und DeleteCommandsowie eine variable 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, deren Ausführung außergewöhnlich lange dauerte. Wenn Sie den TableAdapter zum Ausführen einer dieser Abfragen verwenden, sollten Sie die Eigenschaft des Befehlsobjekts CommandTimeouterhöhen. Diese Eigenschaft gibt die Anzahl der Sekunden an, die auf die Ausführung des Befehls gewartet werden müssen, und wird standardmäßig auf 30 festgelegt.

Damit die CommandTimeout -Eigenschaft von der BLL angepasst werden kann, fügen Sie die folgende public Methode mit der ProductsDataTable in Schritt 2 (ProductsTableAdapter.ConnectionAndCommandSettings.cs) erstellten partiellen Klassendatei hinzu:

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 Präsentationsebene aufgerufen werden, um das Befehlstimeout für alle Befehlsprobleme von diesem TableAdapter-instance festzulegen.

Hinweis

Die Adapter Eigenschaften und CommandCollection sind als privategekennzeichnet, was bedeutet, dass nur über Code innerhalb des TableAdapters auf sie zugegriffen werden kann. Connection Im Gegensatz zur -Eigenschaft sind diese Zugriffsmodifizierer nicht konfigurierbar. Wenn Sie Eigenschaften auf Befehlsebene für andere Ebenen in der Architektur verfügbar machen müssen, müssen Sie daher den oben beschriebenen Ansatz für partielle Klassen verwenden, um eine Methode oder Eigenschaft public bereitzustellen, die die Befehlsobjekte liest oder in diese private schreibt.

Zusammenfassung

Die TableAdapters in einem typisierten DataSet dienen zum Kapseln von Datenzugriffsdetails und -komplexität. Bei Verwendung von TableAdapters müssen wir uns nicht darum kümmern, ADO.NET Code zu schreiben, um eine Verbindung mit der Datenbank herzustellen, einen Befehl auszugeben oder die Ergebnisse in eine DataTable aufzufüllen. Alles wird für uns automatisch abgewickelt.

Es kann jedoch vorkommen, dass wir die ADO.NET Besonderheiten auf niedriger Ebene anpassen müssen, z. B. das Ändern des Verbindungszeichenfolge oder der Standardverbindungs- oder Befehlstimeoutwerte. Der TableAdapter verfügt über automatisch generierte ConnectionEigenschaften , Adapterund CommandCollection , die standardmäßig entweder internal oder privatesind. Diese internen Informationen können verfügbar gemacht werden, indem Sie den TableAdapter mithilfe von partiellen Klassen erweitern, um Methoden oder Eigenschaften einzuschließen public . Alternativ kann der TableAdapter-Eigenschaftsmodifizierer Connection über die TableAdapter-Eigenschaft ConnectionModifier konfiguriert werden.

Viel Spaß beim Programmieren!

Zum Autor

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

Besonderen Dank an

Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Leitende Prüfer für dieses Tutorial waren Burnadette Leigh, S ren Jacob Lauritsen, Teresa Murphy und Hilton Geisenow. Möchten Sie meine anstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.