Interrogazioni multiple di SQL Server 2005 con MARS

3 pagine in totale: <<Indietro 1 [2] 3 Avanti >>

Il ciclo interno sulla relazione può produrre un output diretto oppure può essere consumato da griglie che si occupano di rappresentazioni parent/child, come pure da componenti client.

A seconda delle colonne coinvolte nelle proiezioni, tale tipo di soluzione è altamente aggiornabile, permettendo in definitiva tutto l'insieme delle operazioni C(reate) R(ead) U(pdate) D(elete).

Il piatto completo offerto dal modello ADO.NET ha anche chiaramente pregi anche di completa navigabilità, in tutte le direzioni.

Come svantaggio possiamo sicuramente riportare la pesantezza del modello, vista la necessità di dover consentire movimentazioni di tipo cursore complete.

La cura dimagrante: i DataReader e i MARS

SQL Server 2005 aggiunge all'arsenale disponibile un ulteriore elemento, i Multiple Active Result Set(s).

Questi si fondano su un elemento fondamentale dell'accesso ai dati lato client, il DataReader, che viene implementato a livello server similarmente ad un cursore server-side, forward-only (il cosidetto cursore firehose o "idrante") ad altissime prestazioni e bassissimo impatto in termini di risorse.

Le righe prodotte dal query execution engine vengono copiate direttamente in network buffer pre-allocati. Il risultato è uno stream di dati continuo che viene ritornato al chiamante sullo stack del protocollo di rete e utilizzato in modo immediato e diretto dal chiamante stesso nel più breve tempo possibile, al fine di consentire lo scorrimento del cursore (solo in avanti e con posizionamento esclusivo sulla riga successiva) sino al completo popolamento del cursore stesso, con suo esaurimento e possibilità di rilascio.

Il mancato consumo del default resultset comporta il riempimento dei buffer fino al loro esaurimento e conseguente sospensione del working thread in esecuzione fino a che il client driver non ne riprenda il consumo.

Questa funzionalità è da sempre presente in ADO.NET, sin dall'originale rilascio, ma con una limitazione (per il consumatore) penalizzante. Nelle versioni precedenti uno ed un solo DataReader poteva essere aperto e utilizzato per ogni connessione. Era quindi necessario consumare (e rilasciare) interamente il DataReader attivo prima di poterne attivare uno alternativo/successivo, ovvero aprire più connessioni al fine di poter utilizzare altri Reader.

Questa limitazione è stata risolta in SQL Server 2005 (tutte le edizioni) con l'implementazione dei MARS.

La tecnologia sottostante rimane invariata, come nello stesso modo è rimasto immutato il consumo, che continua ad avvenire tramite DataReader, ma più di uno di questi può contemporaneamente essere aperto sulla stessa connessione. Va comunque precisato che questo non è il limite dei MARS, che in effetti non costituiscono, di sé, un accesso sequenziale di risultati da SQL Server, ma costituiscono la possibilità finora non presente di avere svariati resultset, attivi ed indipendenti gli uni dagli altri come se legati a connessioni specifiche, ma utilizzando la medesima connessione. Ciò sta a significare che non solo operazioni di data-retrival (e quindi DataReader) possono essere associate ai MARS, ma anche un insieme di operazioni atomiche, anche multi-statement, costruite su più batch.

Se questa affermazione può sembrare poca cosa o di poco conto, va inquadrata ad esempio in un'ottica di accesso via Web, con centinaia o anche migliaia di richieste contemporanee, che fino ad ora richiedevano, per alcuni compiti, più di una connessione, con un costo elevatissimo (e talvolta anche eccessivo) in termini di risorse.

Tornando all'esempio trattato nell'articolo, il tutto potrebbe essere quindi modificato come segue.

Dim con As New SqlClient.SqlConnection
With con
  .ConnectionString = "Server=(Local);Database=tempdb;Trusted_Connection=True;Persist Security Info=False;MultipleActiveResultSets=true;"
  .Open()
End With

Dim cmd As New SqlClient.SqlCommand
With cmd
  .CommandText = "Select Id, Descrizione FROM [Ristorazione].[Menu] ORDER BY Id;"
  'ma useremmo una stored procedure
  .CommandType = CommandType.Text
  .CommandTimeout = 0
  .Connection = con
End With

Using dr As SqlClient.SqlDataReader = cmd.ExecuteReader()
  While dr.Read
    Debug.WriteLine(dr("Descrizione"))

    Dim Param As String = dr("Id")
    Dim cmdInner As New SqlClient.SqlCommand
    With cmdInner
      .CommandText = String.Format("SELECT p.Descrizione, mp.IdMenu FROM [Ristorazione].[Pietanze] p JOIN [Ristorazione].[Menu_Pietanze] mp ON p.Id = mp.IdPietanza WHERE mp.IdMenu = {0} ORDER BY IdMenu, Sequenza;", Param)
      'ma useremmo una stored procedure
      .CommandType = CommandType.Text
      .CommandTimeout = 0
      .Connection = con
    End With
    Using drInner As SqlClient.SqlDataReader = cmdInner.ExecuteReader()
      While drInner.Read
        Debug.WriteLine(ControlChars.Tab & drInner("Descrizione"))
      End While
    End Using
  cmdInner.Dispose()
  cmdInner = Nothing

  End While
End Using
cmd.Dispose()
cmd = Nothing
con.Dispose()
con = Nothing

Il risultato risulta essere simile, a livello di presentation layer, a quanto già visto in precedenza.

Menu  
Il gusto della carne Ciclo interno sul DataReader addizionale...
Tagliatelle al ragout di coniglio
Arrosto di spalla di vitello in 'Pan Brioche' à la glace
Cosciotto di lattonzolo ai profumi di sottobosco
Patate al saleprofumato e verdure di campo
Sapori di mari vicini Ciclo interno sul DataReader addizionale...
Passatelli ai cuori di carciofo e calamari
Filetto di tonno su misticanza di verdure con lenticchie di cappero al balsamico
Punte di asparago all'olio di frantoio
Piccoli Ospiti Ciclo interno sul DataReader addizionale...
Cotoletta alla milanese
Patate fritte

La differenza in questo caso è che non stiamo utilizzando un modello completo, navigabile e probabilmente aggiornabile, con tutti i costi in termini di risorse che tutto ciò comporta, bensì un data-pump prestazionalmente eccezionale e con scarsissime richieste in termini di risorse utilizzate. La connessione utilizzata resta la medesima, quindi non si pagano neppure i costi in termini di tempo di connessione associabili ad una simile soluzione basata su SQL Server 2000.

3 pagine in totale: <<Indietro 1 [2] 3 Avanti >>

Attenzione: Questo articolo contiene un allegato

Contenuti dell'articolo

Commenti
Dai un voto a questo articolo, ci aiuterà a migliorare il nostro sito (1 è il voto minimo, 5 il massimo).

Per procedere al rating dell'articolo devi essere autenticato.

TUTORIALS
TOP TEN ARTICOLI
NOTIFICHE

Iscriviti alla nostra newsletter nuoviarticoli per ricevere e-mail le notifiche!

Indirizzo e-mail:
PROVIDER ASP.NET 2.0

Seleziona il database per avere il web.config pronto per Membership, Roles e Profile API.



IN EVIDENZA
MISC