c#ADO.NET / 用 SqlBulkCopy 类,海量批写入数据库

SqlBulkCopy 类,使您可以用其他源的数据有效批量加载 SQL Server 表。

Microsoft SQL Server 提供一个称为 bcp 的流行的命令提示符实用工具,用于将数据从一个表移动到另一个表(表既可以在同一个服务器上,也可以在不同服务器上)。SqlBulkCopy 类允许编写提供类似功能的托管代码解决方案。还有其他将数据加载到 SQL Server 表的方法(例如 INSERT 语句),但相比之下 SqlBulkCopy 提供明显的性能优势。

使用 SqlBulkCopy 类只能向 SQL Server 表写入数据。但是,数据源不限于 SQL Server;可以使用任何数据源,只要数据可加载到 DataTable instance 或可使用 DataReader 读取数据。

----------------------------------------------------------------

示例一:
同上方 msdn 连接的写法,不透过 DataTable 暂存所有要批写入的数据,而是直接用 
DataReader + SqlBulkCopy 类,即时海量地批写入 :

简易示例
using(SqlConnection Conn = new SqlConnection(strConnString))
{
Conn.Open();
SqlCommand Comm
= new SqlCommand("SELECT EmployeeID, LastName, FirstName FROM Employees", Conn);

SqlDataReader dr;

dr
= Comm.ExecuteReader();
using (SqlConnection bcConn = new SqlConnection(strConnString))
{
bcConn.Open();
using (SqlBulkCopy bc = new SqlBulkCopy(bcConn))
{
//要存入的数据库
bc.DestinationTableName = "dbo.TestEmployees";

//字段对应
bc.ColumnMappings.Add("EmployeeID", "EmployeeID");
bc.ColumnMappings.Add(
"LastName", "LastName");
bc.ColumnMappings.Add(
"FirstName", "FirstName");
try
{
 
for (int i = 0; i < 1000; i++)
  bc.WriteToServer(dr);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
if (dr != null)
dr.Close();
}
}
}

在發現了 SqlBulkCopy 以後,發現它更是威力強大,現在就來介紹 SqlBulkCopy 的猛,如下例 :
示例二 :
(此例为先将要批写入的所有数据,暂存在一个 DataTable 里)

进阶示例
//一开始我们先产生一个 DataTable,用来装我们要写入的数据
DataTable dt = new DataTable();
dt.Columns.Add(
"id", typeof(int));
dt.Columns.Add(
"name", typeof(string));

//因为 SqlBulkCopy 的猛,就是海量地快速一次性写入能力,我们來跑 10 万条吧
int i;
for (i = 0; i < 100000; i++)
{
DataRow dr
= dt.NewRow();
dr[
"name"] = i.ToString();
dt.Rows.Add(dr);
}

//声明连接字符串
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ASPNETDBConnectionString1"].ConnectionString);

conn.Open();

//声明 SqlBulkCopy
using (SqlBulkCopy sqlBC = new SqlBulkCopy(conn))
{
//設置一个批,写入多少条记录
sqlBC.BatchSize = 1000;

//設置逾時的秒数
sqlBC.BulkCopyTimeout = 60;

//設置 NotifyAfter 属性,以便在每拷贝 10000 条记录至数据表後,呼叫事件处理函数
sqlBC.NotifyAfter = 10000;
sqlBC.SqlRowsCopied
+= new SqlRowsCopiedEventHandler(OnSqlRowsCopied);

//設置要写入的数据库
sqlBC.DestinationTableName = "dbo.Table1";

//对应数据行
sqlBC.ColumnMappings.Add("id", "id");
sqlBC.ColumnMappings.Add(
"name", "name");

//开始写入
sqlBC.WriteToServer(dt);
}

conn.Dispose();

void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
{
Response.Write(
"---<br/>");
}

  • 測試環境:SQL2005 Express
  • 測試資料量:10 万条
  • 測試次數:10 次
  • 平均秒數:2.3532 秒

结论:太可怕啦,之前的写法,如果真的要写入 10 万条這种海量的数据,都需花费一分钟左右,但使用了 SqlBulkCopy 卻只要短短的兩秒钟。下表看的出來,如果记录条数很少,就沒必要使用 SqlBulkCopy 了。

  • 寫入十万条记录 10 次的平均秒數
    • 使用SqlBulkCopy:2.2051
    • 使用AddWithValue:63.418
  • 寫入一万条记录 10 次的平均秒數
    • 使用SqlBulkCopy:0.2188
    • 使用AddWithValue:6.3856
  • 寫入一千条记录 10 次的平均秒數
    • 使用SqlBulkCopy:0.0187
    • 使用AddWithValue:0.5805
  • 寫入一百条记录 10 次的平均秒數
    • 使用SqlBulkCopy:0.0062
    • 使用AddWithValue:0.0353
  • 寫入十条记录 10 次的平均秒數
    • 使用SqlBulkCopy:0.004
    • 使用AddWithValue:0.004
原文地址:https://www.cnblogs.com/andy_tigger/p/2393262.html