Re giải pháp cho SqlBulkCopy, tôi tạo ra một lớp hơn mất Datatable
hoặc một List<T>
và một Buffer kích thước (CommitBatchSize
). Nó sẽ chuyển đổi danh sách thành một bảng dữ liệu bằng cách sử dụng một phần mở rộng (trong lớp thứ hai).
Nó hoạt động rất nhanh. Trên PC của tôi, tôi có thể chèn hơn 10 triệu bản ghi phức tạp trong vòng chưa đến 10 giây.
Đây là lớp:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DAL
{
public class BulkUploadToSql<T>
{
public IList<T> InternalStore { get; set; }
public string TableName { get; set; }
public int CommitBatchSize { get; set; }=1000;
public string ConnectionString { get; set; }
public void Commit()
{
if (InternalStore.Count>0)
{
DataTable dt;
int numberOfPages = (InternalStore.Count/CommitBatchSize) + (InternalStore.Count % CommitBatchSize == 0 ? 0 : 1);
for (int pageIndex = 0; pageIndex < numberOfPages; pageIndex++)
{
dt= InternalStore.Skip(pageIndex * CommitBatchSize).Take(CommitBatchSize).ToDataTable();
BulkInsert(dt);
}
}
}
public void BulkInsert(DataTable dt)
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
// make sure to enable triggers
// more on triggers in next post
SqlBulkCopy bulkCopy =
new SqlBulkCopy
(
connection,
SqlBulkCopyOptions.TableLock |
SqlBulkCopyOptions.FireTriggers |
SqlBulkCopyOptions.UseInternalTransaction,
null
);
// set the destination table name
bulkCopy.DestinationTableName = TableName;
connection.Open();
// write the data in the "dataTable"
bulkCopy.WriteToServer(dt);
connection.Close();
}
// reset
//this.dataTable.Clear();
}
}
public static class BulkUploadToSqlHelper
{
public static DataTable ToDataTable<T>(this IEnumerable<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
}
}
Dưới đây là một ví dụ khi tôi muốn chèn một danh sách các đối tượng tùy chỉnh của tôi List<PuckDetection>
(ListDetections
):
var objBulk = new BulkUploadToSql<PuckDetection>()
{
InternalStore = ListDetections,
TableName= "PuckDetections",
CommitBatchSize=1000,
ConnectionString="ENTER YOU CONNECTION STRING"
};
objBulk.Commit();
Chắc chắn kiểm tra [ câu hỏi này] (http://stackoverflow.com/questions/629455/how-should-i-optimize-multiple-calls-in-my-net-code-to-a-trivial-stored-procedur). Câu trả lời topvoted (không, nó không phải của tôi: p) trình bày một giải pháp rất thanh lịch cho vấn đề chính xác này. – Brann
cảm ơn bạn đã đặt câu hỏi này –