C'è un modo più veloce per utilizzare SqlBulkCopy rispetto all'utilizzo di un DataTable?

c# sqlbulkcopy sql-server

Domanda

Carico una grande quantità di record nella mia applicazione (1 milione +) e faccio un sacco di elaborazione su di essi. L'elaborazione richiede che tutti siano nella memoria.

Successivamente, voglio scaricare tutti i record (ora modificati) in una tabella vuota.

Il caricamento dei record richiede solo pochi secondi e MyRecord con una vasta gamma di elementi MyRecord .

Il salvataggio con SqlBulkCopy richiede anche solo pochi secondi.

Tuttavia SqlBulkCopy richiede (credo) un DataTable - e il caricamento dei miei record in un DataTable è lento - circa 7500 record al minuto usando

dataTable.Rows.Add(myRecord.Name, myRecord.Age, ....)

C'è un modo più veloce per eseguire questa fase intermedia?

Risposta accettata

Il ritardo è causato dal fatto che devi bufferizzare tutto in un DataTable prima di inviarlo al server. Per ottenere prestazioni migliori, è necessario inviare immediatamente i record a SqlBulkCopy e lasciare che la classe utilizzi il proprio buffer e batch.

SqlBulkCopy può funzionare con IDataReader. Tutti i lettori di dati ADO.NET implementano questa interfaccia, quindi è possibile inviare a SqlBulkCopy i dati letti da qualsiasi lettore di dati.

In altri casi, supponendo di avere un oggetto IEnumerable, è possibile utilizzare ObjectReader di Marc Gravel dal pacchetto FastMember per creare un IDataReader in cima a IEnumerable. Questo lettore di dati non carica tutto in una volta, quindi nessun dato viene memorizzato nella cache finché SqlBulkCopy non lo richiede:

Copiando l'esempio di Marc Gravel:

IEnumerable<SomeType> data = ... 

using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) 
{ 
  bcp.DestinationTableName = "SomeTable"; 
  bcp.WriteToServer(reader); 
}

Risposta popolare

Non so quale sia il problema. Il programma in basso funziona al di sotto di un secondo. Sospetto che la bassa velocità sia dovuta alla lettura dei dati e alla mancata scrittura su DataTable.

       static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Col A", typeof(int));
            dt.Columns.Add("Col B", typeof(string));
            dt.Columns.Add("Col C", typeof(int));
            dt.Columns.Add("Col D", typeof(string));
            dt.Columns.Add("Col E", typeof(int));
            dt.Columns.Add("Col F", typeof(string));
            dt.Columns.Add("Col G", typeof(int));
            dt.Columns.Add("Col H", typeof(string));
            dt.Columns.Add("Col I", typeof(int));
            dt.Columns.Add("Col J", typeof(string));

            DateTime begin = DateTime.Now;

            for (int i = 0; i < 7500; i++)
            {
                dt.Rows.Add(new object[] {
                    i + 10000, "b", i + 20000, "d", i + 30000, "f", i + 40000, "h", i + 50000, "i"
                });
            }

            DateTime end = DateTime.Now;

            Console.WriteLine((end - begin).ToString());

            Console.ReadLine();
        }


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow