2010-10-12 10 views
21

nasıl basit nesnenin bir List <> dan SqlBulkCopy ile büyük ekleme yapabilir>?SqlBulkCopy <

Özel IDataReader'ımı uygularım?

+0

Geç partiye Ancak, bu EntityDataReader sınıfını eklerseniz, tam olarak bunu yapan bir AsDataReader() uzantısı yöntemi vardır: https: // github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs – RJB

+0

(tam uygulama için aşağıdaki yeni cevaba bakın) – RJB

cevap

19

Basitçe nesnelerin listenizden create a DataTable ve veri tablosu geçerek SqlBulkCopy.WriteToServer diyoruz.

Aşağıdaki yarayabilecek:

SqlBulkCopy ile maksimum performans için, uygun bir BatchSize ayarlamalısınız. 10.000 iyi çalışıyor gibi görünüyor - ama verileriniz için profil. SqlBulkCopyOptions.TableLock kullanırken

Ayrıca daha iyi sonuçlar gözlemlemek olabilir.

SqlBulkCopy performansının ilginç ve bilgilendirici analizler here bulunabilir. ObjectReader da olmayan çalışabilirsiniz

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

Not olun: FastMember ile

40

, hiç (performans daha-daha-iki katına benim testlerde,) DataTable yoluyla gitmeye gerek kalmadan bunu yapabilirsiniz (muhtemelen ObjectReader kendisi bunları belirtmek yoksa SqlBulkCopy ait ColumnMappings yönünü kullanmak istiyorum rağmen) genel kaynaklar ve önceden üye adlarını belirtmek için gerekli değildir.

+0

Mükemmel kütüphane! Hemen şimdi denedim ve harika çalışıyor. – alex

+0

Bunun birkaç ay öncesinden olduğunu biliyorum, ancak benzer bir sorun yaşıyorum. Önce DataTable'ı yüklemek çok uzun sürüyor, bu yüzden bu yöntemi kullanmak istedim. Bununla birlikte, params değişkeninde listelenen dizgiler, alttaki veri yapısının üzerinde durduğu nesneden sıraya göre kullanılan değişkenlerin gerçek isimleridir. – JNYRanger

+0

Scratch - bunu anladım ve cevabı evet, bunlar nesnenin içindeki özelliklerin isimleridir. – JNYRanger

1

İlk olarak SqlBulkCopy numaralı telefonu arayarak yapmaya çalıştığınız şeye bağlı olarak, Tablo Değerli Parametre (TVP) kullanmak daha mantıklı olabilir. Bir TVP kullanmak, herhangi bir özel türden bir koleksiyonda göndermeyi önemsiz kılar. Veriler akışa alınabilir, böylece DataTable'dan (@Marc Gravell'in cevabında olduğu gibi) kaçınılabilir ve SqlBulkCopy'u da önleyebilirsiniz. TVP'leri, TVP verisini geçmek için bir Depolanmış Prosedürü çağırdığınızda SQL Server'a ulaştığında verileri nasıl ele alacağınıza tamamen esneklik sağlar ve sadece INSERT ile değil, her şeyi yapabileceğiniz bir Tablo Değişkeni olarak görünür. SqlBulkCopy ile durum). Ayrıca, yeni oluşturulan IDENTITY değerleri gibi verileri SqlDataReader aracılığıyla geri alabilirsiniz. Bu yanıtla ilgili bir örnek ve bazı ek notlar ekledim: How can I insert 10 million records in the shortest time possible?. Ve birkaç yıl önce, SQL Server Central'da (ücretsiz kayıt gerekli), Streaming Data Into SQL Server 2008 From an Application'da bir makale yazdım. Bu raporda ayrıca, 3 milyondan başlayarak özel bir türden bir Genel Listede geçen bir çalışma örneği sunan bağlantılı bir cevaba da dikkat çekildi. satır metni dosyası.

5

partiye Geç ama Microsoft'tan bu EntityDataReader sınıf eklerseniz işte bunu yapıyor bir AsDataReader() uzatma yöntemi var: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

(örnek [List].AsDataReader() uygulama :)

var connStr = ""; 
using (var connection = new SqlConnection(connStr)) 
{ 
    var startTime = DateTime.Now; 
    connection.Open(); 
    var transaction = connection.BeginTransaction(); 
    try 
    { 
     //var connStr = connection.ConnectionString; 
     using (var sbCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction)) 
     { 
      sbCopy.BulkCopyTimeout = 0; 
      sbCopy.BatchSize = 10000; 
      sbCopy.DestinationTableName = "Foobars"; 
      var reader = Foobars.AsDataReader(); 
      sbCopy.WriteToServer(reader); 
     } 
     transaction.Commit(); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
     transaction.Rollback(); 
    } 
    finally 
    { 
     transaction.Dispose(); 
     connection.Close(); 
     var endTime = DateTime.Now; 
     Console.WriteLine("Upload time elapsed: {0} seconds", (endTime - startTime).TotalSeconds); 
    } 
} 
İlgili konular