Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
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 INSERT
kommando , UPDATE
, DELETE
eller 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.
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.
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.
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
.
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.
Steg 3: Undersöka egenskaperna för Command-Related
En TableAdapter består av en huvudfråga som som standard har automatiskt genererade INSERT
, UPDATE
och 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
, UpdateCommand
och 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
, Adapter
och 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.