Dela via


Konfigurera dataåtkomstlagrets anslutnings- och Command-Level inställningar (C#)

av Scott Mitchell

Ladda ned PDF

TableAdapters i en Typed DataSet tar automatiskt hand om att ansluta till databasen, utfärda kommandon och fylla i en DataTable med resultatet. Det finns dock tillfällen då vi själva vill ta hand om den här informationen, och i den här självstudien lär vi oss att komma åt inställningarna för databasanslutning och kommandonivå i TableAdapter.

Inledning

I självstudieserien har vi använt Typed DataSets för att implementera dataåtkomstskiktet och affärsobjekten i vår skiktade arkitektur. Som beskrivs i den första självstudien fungerar DataTables från Typed DataSet som lagringsplatser för data, medan TableAdapters fungerar som inkapslare för att kommunicera med databasen och för att hämta och ändra den underliggande datan. TableAdapters kapslar in komplexiteten i arbetet med databasen och sparar oss från att behöva skriva kod för att ansluta till databasen, utfärda ett kommando eller fylla i resultaten i en DataTable.

Det finns dock tillfällen då vi behöver gräva i djupet av TableAdapter och skriva kod som fungerar direkt med ADO.NET objekt. I självstudiekursen Omsluta databasändringar i en transaktion har vi till exempel lagt till metoder i TableAdapter för att starta, checka in och återställa ADO.NET transaktioner. Dessa metoder använde ett internt, manuellt skapat SqlTransaction objekt som tilldelades TableAdapter-objekten SqlCommand .

I den här självstudien kommer vi att undersöka hur du kommer åt inställningarna för databasanslutning och kommandonivå i TableAdapter. I synnerhet kommer vi att lägga till funktioner i ProductsTableAdapter som ger åtkomst till den underliggande anslutningssträngen och inställningarna för tidsgränsen för kommandon.

Arbeta med data med hjälp av ADO.NET

Microsoft .NET Framework innehåller en mängd klasser som utformats specifikt för att arbeta med data. Dessa klasser, som finns i System.Data namnområdet, kallas för ADO.NET klasser. Vissa av klasserna under ADO.NET paraply är knutna till en viss dataprovider. Du kan se en dataprovider som en kommunikationskanal som gör att information kan flöda mellan de ADO.NET klasserna och det underliggande datalagret. Det finns generaliserade leverantörer, som OleDb och ODBC, samt leverantörer som är särskilt utformade för ett visst databassystem. Även om det till exempel är möjligt att ansluta till en Microsoft SQL Server-databas med oledb-providern är SqlClient-providern mycket effektivare eftersom den har utformats och optimerats specifikt för SQL Server.

Vid programmatisk åtkomst till data används ofta följande mönster:

  • Upprätta en anslutning till databasen.
  • Utfärda ett kommando.
  • För SELECT frågor kan du arbeta med de resulterande posterna.

Det finns separata ADO.NET klasser för att utföra vart och ett av dessa steg. Om du till exempel vill ansluta till en databas med hjälp av SqlClient-providern använder du SqlConnection klassen . Om du vill utfärda ett INSERTkommando , UPDATE, DELETEeller SELECT till databasen använder du SqlCommand klassen .

Förutom Omslut databasändringar inom en transaktion har vi inte behövt skriva någon ADO.NET-kod på låg nivå själva eftersom den automatiskt genererade koden för TableAdapters innehåller de funktioner som krävs för att ansluta till databasen, utfärda kommandon, hämta data och fylla DataTables med dessa data. Det kan dock finnas tillfällen då vi behöver anpassa dessa lågnivåinställningar. Under de kommande stegen kommer vi att undersöka hur du kan utnyttja de ADO.NET objekt som används internt av TableAdapters.

Steg 1: Undersöka med anslutningsegenskapen

Varje TableAdapter-klass har en Connection egenskap som anger databasanslutningsinformation. Den här egenskapens datatyp och ConnectionString värde bestäms av de val som gjorts i guiden TableAdapter-konfiguration. Kom ihåg att när vi först lägger till en TableAdapter i en Typed DataSet frågar den här guiden oss om databaskällan (se bild 1). Listrutan i det här första steget innehåller de databaser som anges i konfigurationsfilen samt andra databaser i Server Explorers dataanslutningar. Om den databas som vi vill använda inte finns i listrutan kan du ange en ny databasanslutning genom att klicka på knappen Ny anslutning och ange nödvändig anslutningsinformation.

Det första steget i konfigurationsguiden för TableAdapter

Bild 1: Det första steget i konfigurationsguiden för TableAdapter (Klicka om du vill visa en bild i full storlek)

Låt oss ägna en stund åt att inspektera koden för TableAdapters egenskap Connection. Som du ser i självstudien Skapa ett dataåtkomstlager kan vi visa den automatiskt genererade TableAdapter-koden genom att gå till fönstret Klassvy, öka detaljnivån till lämplig klass och sedan dubbelklicka på medlemsnamnet.

Gå till fönstret Klassvy genom att gå till menyn Visa och välja Klassvy (eller genom att skriva Ctrl+Skift+C). Från den övre halvan av fönstret Klassvy går du nedåt till NorthwindTableAdapters namnområdet och väljer ProductsTableAdapter klassen. Då visas ProductsTableAdapter medlemmarna i den nedre halvan av klassvyn, enligt bild 2. Dubbelklicka på Connection egenskapen för att se dess kod.

Double-Click Anslutningsegenskapen i Klassvyn för att visa dess automatiskt genererade kod

Bild 2: Double-Click anslutningsegenskapen i klassvyn för att visa dess automatiskt genererade kod

Egenskapen TableAdapter Connection och annan anslutningsrelaterad kod följer:

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;
            }
        }
    }
}

När klassen TableAdapter instansieras är medlemsvariabeln _connection lika med null. När egenskapen Connection används kontrollerar den först om _connection medlemsvariabeln har instansierats. Om den inte har InitConnection anropas InitConnection-metoden, vilket instansierar ConnectionString och anger dess -egenskap till det anslutningssträngsvärde som anges i det första steget av guiden TableAdapter Configuration.

Egenskapen Connection kan också tilldelas till ett SqlConnection objekt. Detta associerar det nya SqlConnection objektet med vart och ett av TableAdapter-objekten SqlCommand .

Steg 2: Visa Connection-Level inställningar

Anslutningsinformationen bör förbli inkapslad i TableAdapter och inte vara tillgänglig för andra lager i programarkitekturen. Det kan dock finnas scenarier när TableAdapter-informationen på anslutningsnivå måste vara tillgänglig eller anpassningsbar för en fråga, användare eller ASP.NET sida.

Vi utökar ProductsTableAdapter i Northwind DataSet till att omfatta en ConnectionString egenskap som kan användas av affärslogiklagret för att läsa eller ändra anslutningssträngen som används av TableAdapter.

Anmärkning

En anslutningssträng är en sträng som anger information om databasanslutning, till exempel vilken provider som ska användas, platsen för databasen, autentiseringsuppgifter och andra databasrelaterade inställningar. En lista över anslutningssträngsmönster som används av en mängd olika datalager och leverantörer finns i ConnectionStrings.com.

Som beskrivs i självstudien Skapa ett dataåtkomstlager kan klasserna Typed DataSet s autogenererade utökas med hjälp av partiella klasser. Skapa först en ny undermapp i projektet med namnet ConnectionAndCommandSettings under ~/App_Code/DAL mappen.

Lägg till en undermapp med namnet ConnectionAndCommandSettings

Bild 3: Lägg till en undermapp med namnet ConnectionAndCommandSettings

Lägg till en ny klassfil med namnet ProductsTableAdapter.ConnectionAndCommandSettings.cs och ange följande kod:

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;
            }
        }
    }
}

Den här partiella klassen lägger till en public egenskap med namnet ConnectionString till ProductsTableAdapter klassen som gör att valfritt lager kan läsa eller uppdatera anslutningssträngen för TableAdapter-underliggande anslutning.

Öppna ProductsBLL-klassen nu när den partiella klassen har skapats (och sparats). Gå till någon av de befintliga metoderna och skriv in Adapter och tryck sedan på periodnyckeln för att ta upp IntelliSense. Du bör se den nya ConnectionString egenskapen som är tillgänglig i IntelliSense, vilket innebär att du programmatiskt kan läsa eller justera det här värdet från BLL:n.

Exponera hela anslutningsobjektet

Den här partiella klassen exponerar bara en egenskap för det underliggande anslutningsobjektet: ConnectionString. Om du vill göra hela anslutningsobjektet tillgängligt utanför TableAdapter kan du också ändra Connection egenskapens skyddsnivå. Den automatiskt genererade koden som vi undersökte i steg 1 visade att egenskapen TableAdapter är Connection markerad som internal, vilket innebär att den endast kan nås av klasser i samma sammansättning. Detta kan dock ändras via egenskapen TableAdapter ConnectionModifier .

Northwind Öppna DataSet, klicka på ProductsTableAdapter i designern och navigera till fönstret Egenskaper. Där kommer du att se ConnectionModifier inställt till dess standardvärde, Assembly. Om du vill göra Connection egenskapen tillgänglig utanför sammansättningen Typed DataSet s ändrar du ConnectionModifier egenskapen till Public.

Tillgänglighetsnivån för anslutningsegenskapen kan konfigureras via egenskapen ConnectionModifier

Bild 4: Egenskapens Connection tillgänglighetsnivå kan konfigureras via egenskapen ConnectionModifier (Klicka om du vill visa en bild i full storlek)

Spara DataSet och återgå sedan till ProductsBLL klassen. Som tidigare går du till någon av de befintliga metoderna och skriver in Adapter och trycker sedan på periodnyckeln för att ta upp IntelliSense. Listan bör innehålla en Connection egenskap, vilket innebär att du nu programmatiskt kan läsa eller tilldela eventuella inställningar på anslutningsnivå från BLL:n.

En TableAdapter består av en huvudfråga som som standard har automatiskt genererade INSERT, UPDATEoch DELETE -instruktioner. Huvudfrågorna INSERT, UPDATE och DELETE -instruktionerna implementeras i TableAdapter s kod som ett ADO.NET dataadapterobjekt via egenskapen Adapter. Precis som med dess Connection egenskap Adapter bestäms egenskapens datatyp av den dataprovider som används. Eftersom dessa självstudier använder SqlClient-providern Adapter är egenskapen av typen SqlDataAdapter.

Egenskapen Adapter för TableAdapter har tre egenskaper av typen SqlCommand som används för att utfärda INSERT, UPDATE och DELETE-uttryck:

  • InsertCommand
  • UpdateCommand
  • DeleteCommand

Ett SqlCommand objekt ansvarar för att skicka en viss fråga till databasen och har egenskaper som: CommandText, som innehåller den ad hoc SQL-instruktionen eller den lagrade procedur som ska köras och Parameters, vilket är en samling SqlParameter objekt. Som vi såg i självstudien Skapa ett dataåtkomstlager kan dessa kommandoobjekt anpassas via fönstret Egenskaper.

Förutom huvudfrågan kan TableAdapter innehålla ett variabelt antal metoder som när det anropas skickar ett angivet kommando till databasen. Huvudfrågans kommandoobjekt och kommandoobjekten för alla ytterligare metoder lagras i egenskapen TableAdapter.CommandCollection

Låt oss ta en stund att titta på koden som genereras av ProductsTableAdapter i Northwind DataSet för dessa två egenskaper och deras stödjande medlemsvariabler och hjälpmetoder:

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;
    }
}

Koden för Adapter egenskaperna och CommandCollection efterliknar nära egenskapens Connection . Det finns medlemsvariabler som innehåller de objekt som används av egenskaperna. Egenskapsåtkomsterna get börjar med att kontrollera om motsvarande medlemsvariabel är null. I så fall anropas en initieringsmetod som skapar en instans av medlemsvariabeln och tilldelar de grundläggande kommandorelaterade egenskaperna.

Steg 4: Visa Command-Level inställningar

Helst bör informationen på kommandonivå förbli inkapslad i dataåtkomstskiktet. Om den här informationen behövs i andra skikt i arkitekturen kan den dock exponeras via en partiell klass, precis som med inställningarna på anslutningsnivå.

Eftersom TableAdapter bara har en enda Connection egenskap är koden för att exponera inställningar på anslutningsnivå ganska enkel. Det är lite mer komplicerat när du ändrar inställningarna på kommandonivå eftersom TableAdapter kan ha flera kommandoobjekt – ett InsertCommand, UpdateCommandoch DeleteCommand, tillsammans med ett variabelt antal kommandoobjekt i CommandCollection egenskapen. När du uppdaterar inställningarna på kommandonivå måste de här inställningarna spridas till alla kommandoobjekt.

Anta till exempel att det fanns vissa frågor i TableAdapter som tog en extra lång tid att köra. När du använder TableAdapter för att köra en av dessa frågor kanske vi vill öka kommandoobjektets CommandTimeout egenskap. Den här egenskapen anger hur många sekunder som ska vänta på att kommandot ska köras och är som standard 30.

För att tillåta att egenskapen CommandTimeout justeras av BLL, lägg till följande public-metod i ProductsDataTable med hjälp av den partiella klassfilen som skapades i steg 2 (ProductsTableAdapter.ConnectionAndCommandSettings.cs):

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;
}

Den här metoden kan anropas från BLL- eller presentationsskiktet för att ange tidsgränsen för kommandot för alla kommandoproblem med den TableAdapter-instansen.

Anmärkning

Adapter och CommandCollection egenskaperna är markerade som private, vilket innebär att de bara kan nås från kod i TableAdapter. Connection Till skillnad från egenskapen kan dessa åtkomstmodifierare inte konfigureras. Om du behöver exponera egenskaper på kommandonivå för andra lager i arkitekturen måste du därför använda den partiella klassmetoden som beskrivs ovan för att tillhandahålla en public metod eller egenskap som läser eller skriver till kommandoobjekten private .

Sammanfattning

TableAdapters i en Typed DataSet används för att kapsla in dataåtkomstinformation och komplexitet. Med TableAdapters behöver vi inte bekymra oss om att skriva ADO.NET kod för att ansluta till databasen, utfärda ett kommando eller fylla i resultatet i en DataTable. Allt hanteras automatiskt för oss.

Det kan dock finnas tillfällen då vi behöver anpassa ADO.NET på låg nivå, till exempel ändra anslutningssträngen eller standardvärdena för anslutning eller tidsgräns för kommandon. TableAdapter har automatiskt genererade Connection, Adapteroch CommandCollection egenskaper, men dessa är antingen internal eller private, som standard. Den här interna informationen kan exponeras genom att utöka TableAdapter med hjälp av partiella klasser till att omfatta public metoder eller egenskaper. Du kan också konfigurera tableAdapter-egenskapens Connection åtkomstmodifierare via egenskapen TableAdapter ConnectionModifier .

Lycka till med programmerandet!

Om författaren

Scott Mitchell, författare till sju ASP/ASP.NET-böcker och grundare av 4GuysFromRolla.com, har arbetat med Microsofts webbtekniker sedan 1998. Scott arbetar som oberoende konsult, tränare och författare. Hans senaste bok är Sams Teach Yourself ASP.NET 2.0 på 24 timmar. Han kan nås på mitchell@4GuysFromRolla.com.

Särskilt tack till

Den här självstudieserien granskades av många användbara granskare. Huvudgranskare för den här handledningen var Burnadette Leigh, Sören Jacob Lauritsen, Teresa Murphy och Hilton Geisenow. Vill du granska mina kommande MSDN-artiklar? Om så är fallet, hör av dig på mitchell@4GuysFromRolla.com.