![](/img/trans.png)
[英]What's the best way to do a bulk namespace rename on a large c# application?
[英]What’s the best way to bulk database inserts from c#?
我如何/什么是批量數據庫插入的最佳方式?
在C#中,我正在迭代一個集合並為集合中的每個項調用插入存儲過程。
如何在一次數據庫調用中發送所有數據?
例如,我說我有一個包含10個項目的人員列表( List<Person>
)。 我目前正在調用InsertPerson存儲過程10次。 我想將此減少到1個電話。
我正在使用MS SQL Server 2005。
CsharperGuyInLondon,這是SqlBulkCopy代碼的一個簡單示例:
using System.Data.SqlClient;
DataTable table = new DataTable("States");
// construct DataTable
table.Columns.Add(new DataColumn("id_state", typeof(int)));
table.Columns.Add(new DataColumn("state_name", typeof(string)));
// note: if "id_state" is defined as an identity column in your DB,
// row values for that column will be ignored during the bulk copy
table.Rows.Add("1", "Atlanta");
table.Rows.Add("2", "Chicago");
table.Rows.Add("3", "Springfield");
using(SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString))
{
bulkCopy.BulkCopyTimeout = 600; // in seconds
bulkCopy.DestinationTableName = "state";
bulkCopy.WriteToServer(table);
}
.NET SqlBulkCopy類運行良好。
您可以構建BLOB(圖像)並將其作為參數發送到存儲過程。 在存儲過程中,您可以使用substring()獲取所有項目。
這是一個很好的SqlBulkCopy
實例:
http://blogs.msdn.com/nikhilsi/archive/2008/06/11/bulk-insert-into-sql-from-c-app.aspx
我將列表構造為xml字符串並將其傳遞給存儲過程。 在SQL 2005中,它具有增強的xml功能,可以解析xml並執行批量插入。
查看這篇文章: 使用XML參數將列表傳遞給SQL Server 2005
對於SqlBulkCopy的解決方案,我創建了一個比采用Datatable
或List<T>
和緩沖區大小( CommitBatchSize
)的類。 它將使用擴展名(在第二個類中)將列表轉換為數據表。
它工作得非常快。 在我的電腦上,我可以在不到10秒的時間內插入超過1000萬條復雜的記錄。
這是班級:
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;
}
}
}
下面是一個示例,當我想插入自定義對象List<PuckDetection>
( ListDetections
)時:
var objBulk = new BulkUploadToSql<PuckDetection>()
{
InternalStore = ListDetections,
TableName= "PuckDetections",
CommitBatchSize=1000,
ConnectionString="ENTER YOU CONNECTION STRING"
};
objBulk.Commit();
將數據轉儲到管道分隔(或其他內容,如果您的數據中有管道)文本文件並使用批量插入 。
您可以使用Xml文檔進行更新,Sql 2005可以很好地與它們配合使用。 每行一個節點,但只有一個Xml參數。
創建一個包含要插入的所有項的XML文檔。 然后在存儲過程內部,使用TSQL xml支持( OPENXML )從XML文檔中讀取所有數據並將其插入到表中,希望每個表都有一個insert語句。
但是,如果您只是將數據插入到單個表中而不需要任何數據庫端邏輯,為什么不使用SqlBulkCopy ?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.