Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Recuperare XML da SQL Server con le API .NET

Esaminiamo le classi che il framework .NET ci mette a disposizione per recuperare dati in formato XML da SQL Server 2000
Esaminiamo le classi che il framework .NET ci mette a disposizione per recuperare dati in formato XML da SQL Server 2000
Link copiato negli appunti

L'introduzione del framework .NET, di cui è imminente il rilascio della nuova versione 2.0, ha cambiato radicalmente l'approccio alla creazione di applicazioni "web oriented" grazie a numerose innovazioni tra cui ricordiamo l'approccio orientato agli oggetti e l'utilizzo del linguaggio XML quale collante tra servizi, applicazioni e framework stesso.

In questo articolo esamineremo le classi (librerie o API) che il framework .NET ci mette a disposizione per recuperare dati in formato XML da SQL Server 2000.

Introduzione ai namespaces

Il framework .NET gestisce in modo gerarchico, attraverso i namespaces (letteralmente spazio dei nomi), le proprie librerie. Essi vengono assegnati sulla base della funzionalità delle classi, per cui in System.Xml troveremo le API che si occupano di gestire l'XML (lettura, scrittura, ecc...) viceversa in System.Data quelle di accesso ai dati.

La libreria ADO.NET

Sotto il nome ADO.NET vengono raccolte tutte le librerie .NET che si occupano gestire l'accesso ai dati (datasources). In particolare quelle necessarie per lavorare con SQL Server sono localizzate sia in System.Data (contiene oggetti generici come il DataSet) che in System.Data.SqlClient (contiene oggetti specializzati per SQL Server come SqlDataReader, ecc.).

Per recuperare dati in formato XML da SQL Server esistono due strategie:

  1. Usare l'oggetto DataSet (disconnesso dalla sorgente dei dati).
  2. Usare l'oggetto SqlDataReader (connesso alla sorgenti dei dati).

Il primo metodo è più semplice da utilizzare ma più lento nelle operazioni di recupero dei dati.

Il secondo metodo è più prestante, ma richiede maggiori attenzioni; il SqlDataReader fisicamente connesso alla sorgente dati, quindi il programmatore deve scrivere le routines necessarie per liberare le risorse allocate al termine della lettura delle informazioni.

L'oggetto XmlReader, il lettore ideale per i documenti/frammenti XML

XmlReader è una classe astratta, in sola lettura e con scorrimento forward-only; una sorta di cursore che permette la lettura del markup XML in modo sequenziale.

Essendo una classe astratta, XmlReader non può essere istanziata direttamente, ma deve prima essere ereditata da un'altra classe che concretamente ne implementi metodi e funzionalità.

//Non è possibile farlo, il compilatore segnala un errore!
XmlReader xr = new XmlReader();

All'interno del framework .NET troviamo tre classi che soddisfano questi requisiti:

  1. XmlTextReader
    Lettore generico per i documenti / frammenti Xml.
  2. XmlValidatingReader
    Legge e verifica documenti XML sulla base di DTD e schemi XSD ad essi abbinati.
  3. XmlNodeReader
    Legge nodi Xml (del tipo XmlNode derivanti dall'implementazione DOM)

//Questo è il modo corretto di usare una classe XmlReader
XmlReader xr = new XmlTextReader( "<ROOT attr='Data'/>", XmlNodeType.Document
,null );
//Leggo il contenuto del documento XML
while(xr.Read())
{
//...faccio delle cose, leggo elementi, nodi attributi, ecc...
}
xr.Close(); //Non dimentichiamo di chiudere il lettore

Queste classi (anche se con funzionalità diverse) rappresentano l'output perfetto per i metodi di accesso ai dati che debbono restituire risultati XML. Ora vediamo questi metodi nel dettaglio.

Usare la classe SqlCommand

La funzione DammiXmlAutoriDaReader ha il compito di eseguire una query con clausola FOR XML su SQL Server e restituire i frammenti XML corrispondenti:

public static XmlReader DammiXmlAutoriDaReader()
{
String thisQuery = "SELECT TOP 10 * FROM dbo.authors Autore FOR XML AUTO,
ELEMENTS;";
//Istanzio un'oggetto StringBuilder che contenta i frammenti XML della query
System.Text.StringBuilder sb = new System.Text.StringBuilder(512);
//Opzionalmente posso specificare un elemento di ROOT, oppure appendere una //DTD
o il riferimento uno schema XSD
//sp.Append("<Autori>");
XmlReader output = null;
//Apro la connessione
using(SqlConnection connection = new SqlConnection(@"Data Source=(local);Database=pubs;Integrated
Security=SSPI;Pooling=true") )
{
//Istanzio il SqlCommand
using( SqlCommand cmd = new SqlCommand(thisQuery,connection) )
{
cmd.CommandType = CommandType.Text;
SqlDataReader dr = cmd.ExecuteReader();
do
{
while(dr.Read()) //Finchè ho dati da leggere...
{
if(!dr.IsDBNull(0)) //Se esiste un contenuto
{
//Appendo il contenuto allo StringBuilder
sb.Append( dr.GetSqlString(0) );
}
}
}while(dr.NextResult()); //Passo al set di dati successivo
dr.Close();
}
}
//Chiudo l'elemento di ROOT
//sp.Append("<Autori />");
//Creo l'oggetto XmlTextReader che implementa l'XmlReader
output = new XmlTextReader(sb.ToString(),XmlNodeType.Element,null);
//Restituisco l'XmlReader al chiamante
return output;
}

I passi sono:

  1. Istanziare un'oggetto di tipo StringBuilder (serve per memorizzare i frammenti Xml localmente).
  2. Creare ed aprire la connessione verso il database tramite SqlConnection.
  3. Creare e formattare con i parametri opportuni l'oggetto SqlCommand.
  4. Eseguire il metodo ExecuteReader di SqlCommand.
  5. Leggere tutto il contenuto del SqlDatReader memorizzando i frammenti XML sull'oggetto StringBuilder.
  6. Chiudere e liberare le risorse allocate (importante).
  7. Istanziare un'oggetto XmlTextReader partendo dai frammenti Xml memorizzati su StringBuilder.
  8. Restituire l'output come XmlReader (il cast da XmlTextReader a XmlReader è implicito)

Questo metodo oltre ad avere una notevole velocità di esecuzione (in quanto legge i dati direttamente dal SqlDataReader) permette di personalizzare l'XML risultante. Ad esempio, possiamo includere i frammenti XML all'interno di un ROOT tag e quindi restituire al chiamante un documento XML ben formato a tutti gli effetti!

Possiamo raggiungere lo stesso risultato anche in altro modo, eseguendo il metodo ExecuteXmlReader esposto dall'oggetto SqlCommand, il quale restituisce direttamente un'oggetto XmlReader, vediamo come modificare l'esempio precedente:

using( SqlCommand cmd = new SqlCommand(thisQuery,connection)
)
{
cmd.CommandType = CommandType.Text;
//L'output restituito è un XmlReader valido (se la query è corretta)
return cmd.ExecuteXmlReader();
}

Le righe di codice sono ridotte all'osso, ma al contrario del primo esempio non possiamo restituire al chiamante un documento XML ben formato, ma solamente i frammenti XML prodotti dalla query!

Usare la classe DataSet

La funzione DammiXmlAutoriDaDataset assolve allo stesso compito ma con un approccio totalmente differente. Vediamo l'esempio in dettaglio:

public static XmlReader DammiXmlAutoriDaDataSet()
{
//Una normalissima SELECT, senza clausola FOR XML
String thisQuery = "SELECT TOP 10 * FROM dbo.authors;";
XmlReader output = null;
System.IO.MemoryStream ms = new System.IO.MemoryStream();
DataSet ds = new DataSet("ROOT_DATI");
using(SqlConnection connection = new SqlConnection(@"Data Source=(local);Database=pubs;Integrated

Security=SSPI;Pooling=true") )
{
using( SqlCommand cmd = new SqlCommand(thisQuery,connection) )
{
cmd.CommandType = CommandType.Text;
using(SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(ds,"Autori");
}
}
}
ds.WriteXml(ms,XmlWriteMode.IgnoreSchema);
ms.Position = 0;
output = new XmlTextReader(ms,XmlNodeType.Element,null);
return output;
}

I passi sono:

  1. Creare un MemoryStream in grado di memorizzare il documento XML.
  2. Creare ed aprire la connessione verso il database tramite l'oggetto SqlConnection.
  3. Creare e formattare con i parametri opportuni l'oggetto SqlCommand.
  4. Riempire tramite l'oggetto SqlDataAdapter il DataSet.
  5. A questo punto utilizziamo il metodo WriteXml dell'oggetto DataSet per scrivere sul MemoryStream il contenuto del DataSet come XML.
  6. Istanziare un'oggetto XmlTextReader partendo dal MemoryStream.
  7. Restituire l'output come XmlReader.

Le differenze rispetto al metodo precedente sono parecchie:

  1. non viene eseguita una query SQL con clausola FOR XML bensì una normalissima SELECT.
  2. il risultato XML viene ottenuto partendo dal contenuto del DataSet quindi il risultato è un documento ben formato!

Questa soluzione offre sicuramente una maggiore portabilità del codice SQL (non siamo vincolati ad utilizzare SQL Server come database per ottenere risultati XML, ma possiamo affidarci anche ad altri databases come Access o MySql), d'altro canto però siamo penalizzati sul fronte della velocità di esecuzione e dal fatto che non possiamo personalizzare "alla fonte" il flusso dei dati XML.

Conclusione

In questo articolo abbiamo utilizzato le librerie .NET per l'accesso ai dati per recuperare flussi XML da SQL Server 2000.


Ti consigliamo anche