Existe-t-il un moyen plus rapide d'utiliser SqlBulkCopy que d'utiliser un DataTable?

c# sqlbulkcopy sql-server

Question

Je charge une grande quantité d'enregistrements dans mon application (1 million et plus) et effectue une tonne de traitement sur eux. Le traitement exige qu'ils soient tous en mémoire.

Ensuite, je veux vider tous les enregistrements (maintenant modifiés) dans une table vide.

Le chargement des enregistrements ne prend que quelques secondes et je me retrouve avec un grand nombre d’éléments MyRecord .

Enregistrer en utilisant SqlBulkCopy prend également quelques secondes.

Cependant, SqlBulkCopy requiert (je crois) un DataTable - et le chargement de mes enregistrements dans un DataTable est lent - environ 7500 enregistrements par minute en utilisant

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

Existe-t-il un moyen plus rapide de réaliser cette étape intermédiaire?

Réponse acceptée

Le retard est dû au fait que vous devez tout mettre en mémoire tampon dans un DataTable avant de l’envoyer au serveur. Pour obtenir de meilleures performances, vous devez immédiatement envoyer les enregistrements à SqlBulkCopy et laisser la classe utiliser sa propre mise en mémoire tampon et son traitement par lots.

SqlBulkCopy peut fonctionner avec un IDataReader. Tous les lecteurs de données ADO.NET implémentent cette interface. Vous pouvez ainsi transférer les données lues depuis n'importe quel lecteur de données vers SqlBulkCopy.

Dans d'autres cas, en supposant que vous avez un IEnumerable de vos objets, vous pouvez utiliser ObjectReader du paquet FastMember de Marc Gravel pour créer un IDataReader au-dessus d'IEnumerable. Ce lecteur de données ne charge pas tout en même temps, donc aucune donnée n'est mise en cache jusqu'à ce que SqlBulkCopy le demande:

Copier l'exemple de 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); 
}

Réponse populaire

Je ne sais pas quel est le problème. Le programme ci-dessous dure moins d'une seconde. Je soupçonne que la lenteur est due à la lecture des données et à l’écriture sur 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();
        }


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi