2012-02-10 40 views
13

Tôi có một truy vấn mà trông như thế này:chèn số lượng lớn với LINQ-to-sql

using (MyDC TheDC = new MyDC()) 
{ 
    foreach (MyObject TheObject in TheListOfMyObjects) 
    { 
     DBTable TheTable = new DBTable(); 

     TheTable.Prop1 = TheObject.Prop1; 
     ..... 
     TheDC.DBTables.InsertOnSubmit(TheTable); 

    } 
    TheDC.SubmitChanges(); 
} 

truy vấn này về cơ bản chèn một danh sách vào cơ sở dữ liệu sử dụng LINQ-to-SQL. Bây giờ tôi đã đọc trực tuyến rằng L2S ​​KHÔNG hỗ trợ hoạt động hàng loạt. Truy vấn của tôi có hoạt động không bằng cách chèn từng phần tử vào một thời điểm hoặc tất cả chúng trong một lần ghi?

Cảm ơn bạn đã làm rõ.

Trả lời

7

Thuật ngữ Bulk Insert thường đề cập đến SQL Server cụ thể cực nhanh bcp dựa trên việc thực hiện SqlBulkCopy. Nó được xây dựng trên đầu trang của IRowsetFastLoad.

LINQ-2-SQL không triển khai chèn bằng cơ chế này, theo mọi điều kiện.

Nếu bạn cần tải số lượng lớn dữ liệu vào SQL Server và cần nó nhanh, tôi khuyên bạn nên viết tay bằng SqlBulkCopy.

LINQ-2-SQL sẽ cố gắng thực hiện một số optimisations để tăng tốc độ chèn nhiều, tuy nhiên nó vẫn sẽ rơi ngắn của nhiều ORMs vi (mặc dù không ORMs vi tôi biết thực hiện SqlBulkCopy)

3

Nó sẽ tạo ra một câu lệnh chèn đơn cho mỗi bản ghi, nhưng sẽ gửi tất cả chúng đến máy chủ trong một gói duy nhất và chạy trong một giao dịch duy nhất.

Đó là những gì SubmitChanges() nằm ngoài vòng lặp.

Nếu bạn di chuyển nó bên trong, sau đó mọi lần lặp qua vòng lặp sẽ chuyển sang máy chủ cho INSERT và chạy trong giao dịch riêng của nó.

Tôi không tin rằng có cách nào để kích hoạt SQL BULK INSERT.

+0

http://stackoverflow.com/a/1329094/17174 đã không kiểm tra l2s chèn Perf chống lại đoan trang trong một thời gian, nhưng tôi đã thử nghiệm ef vs đoan trang ... với kết quả khá thất vọng cho ef https://gist.github.com/1623514 –

26

tôi sửa đổi mã từ liên kết sau để hiệu quả hơn và sử dụng nó trong ứng dụng của tôi. Nó khá thuận tiện bởi vì bạn chỉ có thể đặt nó trong một lớp một phần trên lớp tự động hiện tại của bạn. Thay vì InsertOnSubmit thêm các thực thể vào danh sách và thay vì SubmitChanges, hãy gọi YourDataContext.BulkInsertAll(list).

http://www.codeproject.com/Tips/297582/Using-bulk-insert-with-your-linq-to-sql-datacontex

partial void OnCreated() 
{ 
    CommandTimeout = 5 * 60; 
} 

public void BulkInsertAll<T>(IEnumerable<T> entities) 
{       
    using(var conn = new SqlConnection(Connection.ConnectionString)) 
    { 
     conn.Open(); 

     Type t = typeof(T); 

     var tableAttribute = (TableAttribute)t.GetCustomAttributes(
      typeof(TableAttribute), false).Single(); 
     var bulkCopy = new SqlBulkCopy(conn) 
     { 
      DestinationTableName = tableAttribute.Name 
     }; 

     var properties = t.GetProperties().Where(EventTypeFilter).ToArray(); 
     var table = new DataTable(); 

     foreach (var property in properties) 
     { 
      Type propertyType = property.PropertyType; 
      if (propertyType.IsGenericType && 
       propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
      { 
       propertyType = Nullable.GetUnderlyingType(propertyType); 
      } 

      table.Columns.Add(new DataColumn(property.Name, propertyType)); 
     } 

     foreach (var entity in entities) 
     { 
      table.Rows.Add(
       properties.Select(
       property => property.GetValue(entity, null) ?? DBNull.Value 
       ).ToArray()); 
     } 

     bulkCopy.WriteToServer(table); 
    }            
} 

private bool EventTypeFilter(System.Reflection.PropertyInfo p) 
{ 
    var attribute = Attribute.GetCustomAttribute(p, 
     typeof(AssociationAttribute)) as AssociationAttribute; 

    if (attribute == null) return true; 
    if (attribute.IsForeignKey == false) return true; 

    return false; 
} 
+0

Sử dụng Linqpad Tôi đã phải 't.GetProperties(). Where (EventTypeFilter)' to 't.GetFields()'. Đã chèn 200 nghìn hàng trong ít hơn một phút! (y) –

+0

Không thể nâng cấp đủ điều này. Thử nghiệm của tôi chèn 212 hồ sơ đã được 50s, điều này cắt nó đến 1,3s. Nên giúp đỡ khi tôi thực sự chèn 10k hồ sơ! – Ian

+0

kiểm tra điều này: https://stackoverflow.com/a/21382542/1246870 - đã làm việc tốt cho tôi – avs099

Các vấn đề liên quan