System.Data.SqlClient è il namespace che contiene la definizione delle classi di
Infatti, pur ritenendo valide le idee che erano alla base della filosofia “Universal Data Access”, in Microsoft ci si è resi conto che la stragrande maggioranza delle applicazioni in architettura Windows
Il Sql Server .NET Data Provider
Questo .NET Data Provider è stato realizzato completamente ex-novo, e non contiene nemmeno una riga di codice un-managed. Al suo interno, la presenza di un parser TDS (Tabular Data Stream, il formato di scambio dati che SQL Server utilizza da sempre), garantisce un accesso ottimizzato alle informazioni presenti nel database engine. A differenza dell’OleDb .NET Data Provider, che invece si basa sui servizi OLE DB già conosciuti ed utilizzati da ADO 2.x, e che con i suoi strati di interfacce (seppure ottimizzate) introduce un certo overhead. Queste considerazioni sono ancora più importanti se parliamo di codice che deve essere eseguito lato server, con tutte i requisiti di scalabilità richiesti, ad esempio, da una applicazione Web.

Fig.1 Architettura del SQL Server .NET Data Provider
Tutte le comunicazioni tra il processo client, che utilizza il SQL Server .NET Data Provider, e il database server avvengono sempre utilizzando le Network Libraries, le librerie che consentono a SQL Server di rimanere in ascoluto, su uno o più protocolli di trasporto dei pacchetti di rete, di frames TDS. Quante e quali Network Libraries vengono “attivate” lato server (in realtà vengono sempre installate tutte all’installazione del prodotto) lo si decide in fase di setup di SQL Server o successivamente attraverso l’utility chiamata “Server Network Utility”, che consente, tra le altre cose, anche di configurare la cifratura sui dati trasmessi. Esiste una net-lib di default che è la TCP/IP Socket per la l’edizione Standard e Advanced, mentre è Named Pipes per l’edizione Desktop Engine. Questa scelta è stata fatta in considerazione del fatto che la prima, definita anche “Super-Socket Library” è di gran lunga la più efficente. Esiste un problema però: questa net-lib richiede che venga caricato correttamente sulla macchina lo stack TCP/IP, altrimenti il client (anche processi client sulla stessa macchina) non può comunicare con il server, ecco il motivo per cui viene sempre abilitata di default anche la Named Pipes net-lib.
Lato client, invece, sulle macchine dove è stato installato il supporto a SQL Server, è presente una utility chiamata “Client Network Utility” che consente di abilitare e configurare le net-lib presenti. Altra possibilità è quella di specificare, attraverso l’attributo “Network Library=xxxxxxx” della stringa di connessione, direttamente dal client la net-lib da utilizzare. Ultima possibilità è quella di stabilire, configurando le relative chiavi del registry, qual’è la net-lib di default e quali sono i parametri di funzionamento.
Il consiglio spassionato di Microsoft, è comunque quello di utilizzare la TCP/IP Socket net-lib, date le funzionalità che espone (es. l’encryption basata su SSL) e soprattutto le performance.
SqlClient o SQL Server?
Vi siete chiesti il perchè dello strano nome dato al namespace all’interno del quale sono definite queste classi (System.Data.SqlClient)? Se il server si chiama SQL Server, perchè chiamare il namespace SqlClient? La spiegazione a questa decisione esiste, ed è molto interessante. Attualmente (.NET Framework v1.0) il namespace in questione contiene classi che non offrono nessun supporto “automatizzato” per la gestione di cursori lato server, cioè di strumenti interni al database engine capaci di operare in modalità row-oriented (crea il cursore, muoviti in avanti di un record, leggi il valore dei campi, ecc.), se non attraverso l’utilizzo di specifiche Stored Procedure (sp_cursor, sp_cursorclose, sp_cursorexecute, sp_cursorfetch, sp_cursoropen,ecc.) di sistema inviate attraverso l’oggetto SqlCommand. Ricordate cosa avveniva invece con
Per questo MS ha sempre incoraggiato lo sviluppo di applicazioni “disconnesse” verso la fonte dati, che quindi potessero essere più “leggere” nell’utilizzo delle risorse del server. ADO.NET, nella sua prima versione, favorisce ulteriormente lo sviluppo di applicazioni di questo tipo ma, alcune voci interne a Microsoft, parlano già di un nuovo .NET Data Provider dedicato a SQL Server, che verrà individuato dal namespace System.Data.SqlServer e che conterrà di nuovo il supporto a codice che viene eseguito, in modalità managed, all’interno del processo SQL Server nella prossima versione denominata in codice Yukon, per consentire operazioni avanzate quali le SP nei linguaggi .NET, il caricamento di set di dati in modalità non-logged, e così via.
La connessione a SQL Server
La classe SqlConnection è il punto di partenza dal quale inizieremo ad analizzare il SQL Server .NET Data Provider. Attraverso la definizione di questa classe è possibile interagire con SQL Server, andando a configurare, per esempio, il modo con il quale viene gestito il connection pooling o la modalità di autenticazione scelta dal client.
// Instanzio un nuovo oggetto SqlConnection string scnn = “Server=localhost;Database=Northwind;Trusted_Connection=Yes”; using(SqlConnection cnn = new SqlConnection(scnn)) { try { // Apertura della connessione cnn.Open(); // Eseguo le operazioni sul database... } catch(Exception e) { // gestisco l’eccezione } }
Da un punto di vista logico, questa classe rappresenta una sessione aperta tra il client e il database server o, a livello ancora più basso, una connessione di rete.
La caratteristica fondamentale di una SqlConnection è sicuramente la ConnectionString che può essere impostata utilizzando la relativa proprietà oppure passata come parametro al costruttore. Viene eseguito il parsing subito dopo l’assegnazione di un valore, quindi se qualcosa è errato viene generata una eccezione, tipicamente una ArgumentException. Questa operazione può essere eseguita solo a connessione non ancora aperta, oppure già chiusa, e provoca il reset di tutte le proprietà che vengono impostate dal contenuto della ConnectionString.
L’attributo Persist Security Info (default FALSE) provoca la persistenza della password, specificata in fase di apertura della connessione, all’interno della proprietà ConnectionString. Questo ovviamente può provocare un potenziale problema di sicurezza, ma in certe circostanze evita di dover ripassare ogni volta quella informazione. Attenzione anche a potenziali problemi di sicurezza derivanti dal costruire il valore della proprietà ConnectionString sulla base dell’input di un utente attraverso una DialogBox o simili. Infatti se l’utente immettesse una stringa del tipo “passwordvalida;Database=AltroDatabase” in una TextBox nella quale si richiede solo la password, e questo valore venisse concatenato ad una stringa che definiva già il database al quale collegarsi, la connessione verrebbe aperta verso il nuovo database, posto che l’utente utilizzato abbia i permessi per poterlo fare.
Ancora riguardo alla security, occorre dire che dal punto di vista delle performance l’utilizzo della sicurezza integrata con Windows (“Trusted_Connection=Yes” oppure “Integrated Security=
|
Nome |
Default |
Descrizione |
|
Application Name |
'.Net SqlClient Data Provider' |
Il nome della connessione aperta verso SQL Server. |
|
AttachDBFilename o Initial File Name |
|
Il nome del primary file (full path) di un database “attachable” al momento della apertura della connessione. |
|
Connect Timeout o Connection Timeout |
15 sec. |
Il tempo timeout per l’esecuzione di una operazione verso SQL Server prima di terminare e generare una eccezione. |
|
Connection Lifetime |
0 sec. (timeout massimo) |
Quando la connessione ritorna in un pool, viene verificato se la differenza tra quando è stata creata e l’istante corrente è maggiore del valore specificato, e nel caso viene distrutta. Utile in un ambiente cluster per velocizzare il passaggio da un server ad un’altro in caso di failover. |
|
Connection Reset |
'true' |
Determina se la connessione viene resettata dopo che è stata eliminata da un pool. Settando questo valore a 'false' evita successivi round-trip verso il server in caso di riutilizzo, ma occorre essere consapevoli che lo stato della connessione non è stato resettato (es. security o altre info di connessione). |
|
Current Language |
|
Il tipo di linguaggio utilizzato per i messaggi di errore di SQL Server. |
|
Data Source o Server o Address o Addr o Network Address |
|
Il nome dell’istanza di SQL Server (Es. “SERVER\Istanza”) alla quale connettersi, o il suo indirizzo IP. |
|
Enlist |
'true' |
Il pooler arruola automaticamente questa connessione nel contesto della transazione alla quale il thread corrente appartiene. |
|
Initial Catalog o Database |
|
Nome del database al quale connettersi. |
|
Integrated Security o Trusted_Connection |
'false' |
Sicurezza integrata con Windows. I valori possibili sono 'true', 'false', e 'sspi', che è equivalente a 'true'. |
|
Max Pool Size |
100 |
Numero massimo di connessioni permesse in un pool. |
|
Min Pool Size |
0 |
Numero minimo di connessioni permesse in un pool. |
|
Network Library o Net |
'dbmssocn' |
La network library utilizzata per aprire la connessione con l’istanza di SQL Server. I valori possibili sono: dbnmpntw(Named Pipes) dbmsrpcn(Multiprotocol) dbmsadsn(Apple Talk) dbmsgnet(VIA) dbmsipcn(Shared Memory) dbmsspxn(IPX/SPX) dbmssocn(TCP/IP) La net-lib deve essere installata sul sistema al quale si vuole connettersi. Se si specifica "(local)" o “localhost” di default viene utilizzata shared memory. |
|
Packet Size |
8192 |
Dimensione in bytes dei pacchetti TDS utilizzati per comunicare con SQL Server. Dimensioni possibili tra 512 Byte e 32Kb, da impostare a seconda del tipo di info che vengono scambiate. Di solito si lascia il default, ma in caso di scambio di blocchi di informazioni di grandi dimensioni (immagini, testi, ecc.) può essere utile aumentare il parametro per ridurre i round-trip. |
|
Password o Pwd |
|
La password utilizzata per la login standard di SQL Server specificata per la connessione. |
|
Persist Security Info |
'false' |
Di default le informazioni riguardanti la security non vengono rese disponibili attraverso l’oggetto SqlConnection dopo che la connessione è stata aperta o resettata. Occorre fornirle di nuovo in caso di riapertura. |
|
Pooling |
'true' |
Abilita il pooling per questa connessione. |
|
User ID |
|
La login standard di SQL Server utilizzata per la connessione. |
|
Workstation ID |
Nome della macchina locale |
Il nome della workstation dalla quale si apre la connessione. |
