如何批量插入数据库?
在C#中,我正在遍历一个集合,并为集合中的每个项调用插入存储过程。
如何通过一个数据库调用发送所有数据?
例如,假设我有一个人员列表(List<Person>
),其中包含10个条目。我目前正在调用InsertPerson存储过程10次。我想将此减少到1个调用。
我正在使用MS SQL Server 2005。
如何批量插入数据库?
在C#中,我正在遍历一个集合,并为集合中的每个项调用插入存储过程。
如何通过一个数据库调用发送所有数据?
例如,假设我有一个人员列表(List<Person>
),其中包含10个条目。我目前正在调用InsertPerson存储过程10次。我想将此减少到1个调用。
我正在使用MS SQL Server 2005。
伦敦的CsharperGuy,在这里有一个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);
}
嗯,10个条目并不能算作批量操作,但对于更大的数据集,SqlBulkCopy
是你的好朋友。你只需要提供一个DataTable
或IDataReader
(我更喜欢后者,因为我喜欢流式API)。我曾经在这里做过类似的事情(你可以忽略XML部分 - 只需继承SimpleDataReader即可)。
关于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();
SqlBulkCopy
操作示例:
http://blogs.msdn.com/nikhilsi/archive/2008/06/11/bulk-insert-into-sql-from-c-app.aspx
您可以使用 Xml 文档进行更新,Sql 2005 与其非常兼容。每行一个节点,但只有一个 Xml 参数。