Inserimenti bulk su database con la classe SqlBulkCopy di ADO.NET 2.0

di Cristian Civera, in UserScript, ASP.NET 2.0, ADO.NET,

Nelle applicazioni web e windows capita spesso di avere l'esigenza di importare dati all'interno nostro database SQL Server che siano provenienti da fonti esterne, come file Excel, file testuali con separatori, ecc.
Questi dati possono essere in grande quantità e utilizzare il semplice oggetto SqlCommand può risultare poco performante.
ADO.NET 2.0 mette a disposizione per questo scopo una classe di nome SqlBulkCopy per effettuare inserimenti di massa.
La classe non fa altro che utilizzare una stringa di connessione e in base al nome della tabella specificata, effettua inserimenti a gruppi delle righe. Per istanziarla quindi scriviamo:

// Creo il bulk copy con la stringa di connessione al db
using (SqlBulkCopy bulkCopy = new SqlBulkCopy("Integrated Security=SSPI;Initial Catalog=BulkTest;server=(local)", SqlBulkCopyOptions.UseInternalTransaction))
{
    // Indico il nome della tabella da popolare
    bulkCopy.DestinationTableName = "Contacts";
    // Numero di record per ogni gruppo da inviare al db
    bulkCopy.BatchSize = 500;
    ...
}

Con la proprietà BatchSize indichiamo ogni quanti records viene effettuato il caricamento sul database. E' un parametro molto importante che va calibrato nel modo corretto: un numero troppo basso causa l'esecuzione della query troppo spesso, mentre un numero troppo elevato può sovraccaricare la cache di .NET che accumula i records e in entrambi i casi portare ad un decadimento di performance.

Una volta preparata la classe non dobbiamo far altro che indicare quali sono i dati da caricare chiamando il metodo WriteToServer. Questo accetta una DataTable, un array di DataRow o un oggetto IDataReader. Questa interfaccia è implementata da SqlDataReader, OdbcDataReader, OleDbDataReader e ciò significa che possiamo passare qualsiasi risultato ottenuto chiamando ExecuteReader su database compatibili con Ole-DB, ODBC o SQL Server.
Nell'esempio viene caricato un file testuale separato da tab uploadato dall'utente ed è presente una classe apposita chiamata FlatFileReader che implementa l'interfaccia IDataReader.In alternativa è possibile caricare una DataTable per poi passarla al metodo WriteToServer.

// Apro lo stream inviato
using (StreamReader reader = new StreamReader(file.PostedFile.InputStream)) {

    // Reader per file testuale separato da tab
    using (FlatFileReader flatFile = new FlatFileReader(reader)) {
        // Mando in scrittura il file testuale
        bulkCopy.WriteToServer(flatFile);
    }
}

Questa tecnica permette di incrementare notevolmente l'operazione di caricamento. L'autore lo quantifica sulla propria macchina fino al 95% rispetto al normale inserimento.
L'allegato contiene un file BulkTest.sql per creare un database di test e un file bulk.txt di 20.000 righe per provare il caricamento.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi