Configurazione delle impostazioni del livello di accesso ai dati a livello di connessione e di comando (C#)
Gli oggetti TableAdapter all'interno di un dataset tipizzato si occupano automaticamente della connessione al database, dell'emissione di comandi e del popolamento di un oggetto DataTable con i risultati. Tuttavia, in questa esercitazione viene illustrato come accedere alle impostazioni a livello di database e a livello di comando in TableAdapter.
Introduzione
Nell'intera serie di esercitazioni sono stati usati set di dati tipizzati per implementare il livello di accesso ai dati e gli oggetti business dell'architettura a più livelli. Come illustrato nella prima esercitazione, le tabelle DataTable del set di dati tipizzato fungono da repository di dati, mentre gli oggetti TableAdapter fungono da wrapper per comunicare con il database per recuperare e modificare i dati sottostanti. Gli oggetti TableAdapter incapsulano la complessità dell'uso del database e consentono di scrivere codice per connettersi al database, eseguire un comando o popolare i risultati in una tabella DataTable.
In alcuni casi, tuttavia, quando è necessario scavare nelle profondità dell'oggetto TableAdapter e scrivere codice che funziona direttamente con gli oggetti ADO.NET. Nell'esercitazione Wrapping delle modifiche del database all'interno di una transazione, ad esempio, sono stati aggiunti metodi a TableAdapter per iniziare, eseguire il commit e il rollback delle transazioni ADO.NET. Questi metodi utilizzavano un oggetto creato SqlTransaction
manualmente e interno assegnato agli oggetti TableAdapter SqlCommand
.
In questa esercitazione verrà illustrato come accedere alle impostazioni a livello di comando e connessione del database in TableAdapter. In particolare, si aggiungeranno funzionalità a ProductsTableAdapter
che consente l'accesso alle impostazioni di timeout del stringa di connessione e dei comandi sottostanti.
Uso dei dati tramite ADO.NET
Microsoft .NET Framework contiene un'ampia gamma di classi progettate appositamente per lavorare con i dati. Queste classi, trovate all'interno delloSystem.Data
spazio dei nomi, vengono definite classi ADO.NET. Alcune classi sotto l'ombrello ADO.NET sono associate a un provider di dati specifico. È possibile considerare un provider di dati come un canale di comunicazione che consente il flusso delle informazioni tra le classi ADO.NET e l'archivio dati sottostante. Esistono provider generalizzati, come OleDb e ODBC, nonché provider appositamente progettati per un particolare sistema di database. Ad esempio, sebbene sia possibile connettersi a un database di Microsoft SQL Server usando il provider OleDb, il provider SqlClient è molto più efficiente perché è stato progettato e ottimizzato in modo specifico per SQL Server.
Quando si accede ai dati a livello di codice, viene comunemente usato il modello seguente:
- Stabilire una connessione al database.
- Eseguire un comando.
- Per
SELECT
le query, usare i record risultanti.
Esistono classi ADO.NET separate per l'esecuzione di ognuno di questi passaggi. Per connettersi a un database usando il provider SqlClient, ad esempio, usare la SqlConnection
classe . Per eseguire un INSERT
comando , UPDATE
, DELETE
o SELECT
al database, usare la SqlCommand
classe .
Ad eccezione del wrapping delle modifiche al database all'interno di un'esercitazione sulle transazioni , non è stato necessario scrivere codice di basso livello ADO.NET perché il codice generato automaticamente da TableAdapter include le funzionalità necessarie per connettersi al database, eseguire comandi, recuperare dati e popolare tali dati in DataTable. Tuttavia, potrebbero esserci momenti in cui è necessario personalizzare queste impostazioni di basso livello. Nei passaggi successivi si esaminerà come accedere agli oggetti ADO.NET usati internamente dagli oggetti TableAdapter.
Passaggio 1: Esame della proprietà di connessione
Ogni classe TableAdapter ha una Connection
proprietà che specifica le informazioni di connessione al database. Il tipo di dati e ConnectionString
il valore di questa proprietà sono determinati dalle selezioni effettuate nella Configurazione guidata TableAdapter. Tenere presente che quando si aggiunge un oggetto TableAdapter a un dataset tipizzato, questa procedura guidata richiede l'origine del database (vedere la figura 1). Nell'elenco a discesa di questo primo passaggio sono inclusi i database specificati nel file di configurazione e tutti gli altri database nel Connections dati di Esplora server. Se il database da usare non esiste nell'elenco a discesa, è possibile specificare una nuova connessione al database facendo clic sul pulsante Nuova connessione e specificando le informazioni di connessione necessarie.
Figura 1: Primo passaggio della Configurazione guidata TableAdapter (fare clic per visualizzare l'immagine a dimensione intera)
Esaminare il codice per la proprietà TableAdapter s Connection
. Come indicato nell'esercitazione Creazione di un livello di accesso ai dati , è possibile visualizzare il codice TableAdapter generato automaticamente passando alla finestra Visualizzazione classi, eseguendo il drill-down alla classe appropriata e quindi facendo doppio clic sul nome del membro.
Passare alla finestra Visualizzazione classi passando al menu Visualizza e scegliendo Visualizzazione classi (o digitando CTRL+MAIUSC+C). Nella parte superiore della finestra Visualizzazione classi eseguire il drill-down nello NorthwindTableAdapters
spazio dei nomi e selezionare la ProductsTableAdapter
classe . Verranno visualizzati i ProductsTableAdapter
membri nella metà inferiore della visualizzazione classi, come illustrato nella figura 2. Fare doppio clic sulla proprietà per visualizzarne il Connection
codice.
Figura 2: Double-Click la proprietà Connection nella visualizzazione Classi per visualizzare il codice generato automaticamente
La proprietà tableAdapter Connection
e altro codice correlato alla connessione sono i seguenti:
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;
}
}
}
}
Quando viene creata un'istanza della classe TableAdapter, la variabile _connection
membro è uguale a null
. Quando si accede alla Connection
proprietà, verifica innanzitutto se è stata creata un'istanza della _connection
variabile membro. In caso contrario, viene richiamato il InitConnection
metodo , che crea _connection
un'istanza e ne imposta ConnectionString
la proprietà sul valore stringa di connessione specificato dal primo passaggio della Configurazione guidata TableAdapter.
La Connection
proprietà può anche essere assegnata a un SqlConnection
oggetto . In questo modo, il nuovo SqlConnection
oggetto viene associato a ognuno degli oggetti TableAdapter SqlCommand
.
Passaggio 2: Esposizione delle impostazioni di Connection-Level
Le informazioni di connessione devono rimanere incapsulate all'interno di TableAdapter e non essere accessibili ad altri livelli nell'architettura dell'applicazione. Possono tuttavia verificarsi scenari in cui le informazioni a livello di connessione di TableAdapter devono essere accessibili o personalizzabili per una query, un utente o una pagina ASP.NET.
È possibile estendere ProductsTableAdapter
in Northwind
DataSet per includere una ConnectionString
proprietà che può essere usata dal livello della logica di business per leggere o modificare la stringa di connessione usata dall'oggetto TableAdapter.
Nota
Un stringa di connessione è una stringa che specifica le informazioni di connessione al database, ad esempio il provider da usare, il percorso del database, le credenziali di autenticazione e altre impostazioni correlate al database. Per un elenco di modelli di stringa di connessione usati da un'ampia gamma di archivi dati e provider, vedere ConnectionStrings.com.
Come illustrato nell'esercitazione Creazione di un livello di accesso ai dati , è possibile estendere le classi generate automaticamente di DataSet tipizzato tramite l'uso di classi parziali. Creare prima di tutto una nuova sottocartella nel progetto denominato ConnectionAndCommandSettings
sotto la ~/App_Code/DAL
cartella .
Figura 3: Aggiungere una sottocartella denominata ConnectionAndCommandSettings
Aggiungere un nuovo file di classe denominato ProductsTableAdapter.ConnectionAndCommandSettings.cs
e immettere il codice seguente:
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;
}
}
}
}
Questa classe parziale aggiunge una public
proprietà denominata ConnectionString
alla ProductsTableAdapter
classe che consente a qualsiasi livello di leggere o aggiornare il stringa di connessione per la connessione sottostante di TableAdapter.
Con questa classe parziale creata (e salvata), aprire la ProductsBLL
classe . Passare a uno dei metodi esistenti e digitare Adapter
e quindi premere il tasto punto per visualizzare IntelliSense. Verrà visualizzata la nuova ConnectionString
proprietà disponibile in IntelliSense, vale a dire che è possibile leggere o modificare questo valore a livello di codice dal BLL.
Esposizione dell'intero oggetto connection
Questa classe parziale espone una sola proprietà dell'oggetto connessione sottostante: ConnectionString
. Se si desidera rendere disponibile l'intero oggetto connessione oltre i limiti del TableAdapter, in alternativa è possibile modificare il Connection
livello di protezione della proprietà. Il codice generato automaticamente esaminato nel passaggio 1 ha mostrato che la proprietà TableAdapter è Connection
contrassegnata come internal
, vale a dire che è possibile accedervi solo dalle classi nello stesso assembly. Questa modifica può tuttavia essere modificata tramite la proprietà TableAdapter.ConnectionModifier
Aprire il Northwind
set di dati, fare clic su ProductsTableAdapter
nella Designer e passare alla Finestra Proprietà. Verrà visualizzato il set sul ConnectionModifier
relativo valore predefinito, Assembly
. Per rendere disponibile la Connection
proprietà all'esterno dell'assembly DataSet tipizzato, modificare la ConnectionModifier
proprietà in Public
.
Figura 4: Il Connection
livello di accessibilità della proprietà può essere configurato tramite la ConnectionModifier
proprietà (fare clic per visualizzare l'immagine a dimensione intera)
Salvare l'oggetto DataSet e quindi tornare alla ProductsBLL
classe . Come in precedenza, passare a uno dei metodi esistenti e digitare Adapter
e quindi premere la chiave punto per visualizzare IntelliSense. L'elenco deve includere una Connection
proprietà, ovvero è ora possibile leggere o assegnare a livello di codice le impostazioni a livello di connessione dal BLL.
Passaggio 3: Esame delle proprietà Command-Related
Un oggetto TableAdapter è costituito da una query principale che, per impostazione predefinita, ha istruzioni , UPDATE
e DELETE
generate INSERT
automaticamente. Le istruzioni , UPDATE
e DELETE
della query INSERT
principale vengono implementate nel codice tableAdapter come oggetto adattatore dati ADO.NET tramite la Adapter
proprietà . Analogamente alla relativa Connection
proprietà, il Adapter
tipo di dati della proprietà viene determinato dal provider di dati usato. Poiché queste esercitazioni usano il provider SqlClient, la Adapter
proprietà è di tipo SqlDataAdapter
.
La proprietà TableAdapter ha Adapter
tre proprietà di tipo SqlCommand
usate per rilasciare le INSERT
istruzioni , UPDATE
e DELETE
:
InsertCommand
UpdateCommand
DeleteCommand
Un SqlCommand
oggetto è responsabile dell'invio di una query specifica al database e dispone di proprietà come : CommandText
, che contiene l'istruzione SQL ad hoc o la stored procedure da eseguire; e Parameters
, che è una raccolta di SqlParameter
oggetti . Come illustrato nell'esercitazione Creazione di un livello di accesso ai dati, questi oggetti comando possono essere personalizzati tramite il Finestra Proprietà.
Oltre alla query principale, TableAdapter può includere un numero variabile di metodi che, quando richiamati, inviano un comando specificato al database. L'oggetto comando della query principale e gli oggetti comando per tutti i metodi aggiuntivi vengono archiviati nella proprietà TableAdapter.CommandCollection
Esaminare il codice generato da ProductsTableAdapter
in Northwind
DataSet per queste due proprietà e i relativi metodi helper e variabili membro di supporto:
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;
}
}
Il codice per le Adapter
proprietà e CommandCollection
simula attentamente quello della Connection
proprietà . Esistono variabili membro che contengono gli oggetti utilizzati dalle proprietà. Le funzioni di accesso delle proprietà get
iniziano controllando se la variabile membro corrispondente è null
. In tal caso, viene chiamato un metodo di inizializzazione che crea un'istanza della variabile membro e assegna le proprietà principali correlate ai comandi.
Passaggio 4: Esposizione delle impostazioni di Command-Level
Idealmente, le informazioni a livello di comando devono rimanere incapsulate all'interno del livello di accesso ai dati. Se queste informazioni devono essere necessarie in altri livelli dell'architettura, tuttavia, possono essere esposte tramite una classe parziale, proprio come con le impostazioni a livello di connessione.
Poiché TableAdapter ha solo una singola Connection
proprietà, il codice per esporre le impostazioni a livello di connessione è abbastanza semplice. Le cose sono un po'più complicate quando si modificano le impostazioni a livello di comando perché TableAdapter può avere più oggetti comando - un InsertCommand
oggetto , UpdateCommand
e , DeleteCommand
insieme a un numero variabile di oggetti comando nella CommandCollection
proprietà. Quando si aggiornano le impostazioni a livello di comando, queste impostazioni devono essere propagate a tutti gli oggetti comando.
Si supponga, ad esempio, che in TableAdapter siano state eseguite alcune query che hanno impiegato molto tempo per l'esecuzione. Quando si usa TableAdapter per eseguire una di queste query, è possibile aumentare la proprietà dell'oggetto CommandTimeout
comando. Questa proprietà specifica il numero di secondi per attendere l'esecuzione del comando e il valore predefinito è 30.
Per consentire la regolazione della CommandTimeout
proprietà da parte del BLL, aggiungere il metodo seguente public
all'uso ProductsDataTable
del file di classe parziale creato nel passaggio 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;
}
Questo metodo può essere richiamato dal livello BLL o Presentation per impostare il timeout dei comandi per tutti i problemi dei comandi da tale istanza di TableAdapter.
Nota
Le Adapter
proprietà e CommandCollection
sono contrassegnate come private
, ovvero possono essere accessibili solo dal codice all'interno di TableAdapter. A differenza della Connection
proprietà, questi modificatori di accesso non sono configurabili. Pertanto, se è necessario esporre le proprietà a livello di comando ad altri livelli nell'architettura, è necessario usare l'approccio di classe parziale descritto in precedenza per fornire un metodo o una public
proprietà che legge o scrive negli private
oggetti comando.
Riepilogo
I TableAdapter all'interno di un dataset tipizzato servono per incapsulare i dettagli di accesso ai dati e la complessità. L'uso di TableAdapters non deve preoccuparsi di scrivere codice ADO.NET per connettersi al database, emettere un comando o popolare i risultati in una tabella dati. È tutto gestito automaticamente per noi.
Tuttavia, potrebbero verificarsi momenti in cui è necessario personalizzare le specifiche di ADO.NET di basso livello, ad esempio la modifica del stringa di connessione o i valori di timeout predefinito della connessione o del comando. TableAdapter ha proprietà generate Connection
automaticamente , Adapter
e , CommandCollection
ma queste sono internal
o private
, per impostazione predefinita. Queste informazioni interne possono essere esposte estendendo TableAdapter usando classi parziali per includere public
metodi o proprietà. In alternativa, il modificatore di Connection
accesso alla proprietà TableAdapter può essere configurato tramite la proprietà TableAdapter.ConnectionModifier
Programmazione felice!
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Microsoft Web dal 1998. Scott lavora come consulente indipendente, allenatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2,0 in 24 Ore. Può essere raggiunto a mitchell@4GuysFromRolla.com. o tramite il suo blog, che può essere trovato in http://ScottOnWriting.NET.
Grazie speciali
Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali per questa esercitazione sono stati Burnadette Leigh, S ren Jacob Lauritsen, Teresa Murphy e Hilton Geisenow. Interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami una riga in mitchell@4GuysFromRolla.com.