在.Net1.1中無論是對於批量插入整個DataTable中的所有數據到數據庫中,還是進行不同數據源之間的遷移,都不是很方便。而 在.Net2.0中,SQLClient命名空間下增加了幾個新類幫助我們通過DataTable或DataReader批量遷移數據。數據源可以來自關 系數據庫或者XML文件,甚至WebService返回結果。其中最重要的一個類就是SqlBulkCopy類,使用它可以很方便的幫助我們把數據源的數 據遷移到目標數據庫中。
下面我們先通過一個簡單的例子說明這個類的使用:
首先:web.config
<connectionStrings>
<add name="srcDBConnection" connectionString="server=.;database=pubs;uid=sa;pwd="/>
<add name="desDBConnection" connectionString="server=.;database=NorthWind;uid=sa;pwd="/>
</connectionStrings>
C#文件: 前台不Copy了,就一個按鈕,一個Label
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
public partial class ASP_NET : System.Web.UI.Page
{
private DateTime startTime;
protected void Button1_Click(object sender, EventArgs e)
{
startTime = DateTime.Now;
string srcConnString = "";
string desConnString = "";
SqlConnection srcConnection = new SqlConnection();
SqlConnection desConnection = new SqlConnection();
SqlCommand sqlcmd = new SqlCommand();
SqlDataAdapter da = new SqlDataAdapter();
DataTable dt = new DataTable();
//srcConnString = ConfigurationManager.ConnectionStrings["srcDBConnection"].ConnectionString;
desConnString = ConfigurationManager.ConnectionStrings["desDBConnection"].ToString();
//srcConnection.ConnectionString = srcConnString;
srcConnection.ConnectionString = desConnString;
sqlcmd.Connection = srcConnection;
//sqlcmd.CommandText = "select * from jobs";
sqlcmd.CommandText = "select * from abc";
sqlcmd.CommandType = CommandType.Text;
sqlcmd.Connection.Open();
da.SelectCommand = sqlcmd;
da.Fill(dt);
SqlBulkCopy sbc = new SqlBulkCopy(desConnString,SqlBulkCopyOptions.UseInternalTransaction);
sbc.BulkCopyTimeout = 5000;
sbc.SqlRowsCopied +=new SqlRowsCopiedEventHandler(OnRowsCopied);
sbc.NotifyAfter = dt.Rows.Count;
try
{
// sbc.DestinationTableName = "jobs";
sbc.DestinationTableName = "bcd";
sbc.WriteToServer(dt);
}
catch (Exception ex)
{
lblCounter.Text = ex.Message.ToString();
}
finally
{
sqlcmd.Clone();
srcConnection.Close();
desConnection.Close();
}
}
private void OnRowsCopied(object sender, SqlRowsCopiedEventArgs args)
{
lblCounter.Text += args.RowsCopied.ToString() + " rows are copied<Br>";
TimeSpan copyTime = DateTime.Now - startTime;
lblCounter.Text += "Copy Time:" + copyTime.Seconds.ToString() + "." + copyTime.Milliseconds.ToString() + " seconds";
}
}
代碼分析:
SqlBulkCopy sbc = new SqlBulkCopy(desConnString,SqlBulkCopyOptions.UseInternalTransaction);
先生成SqlBulkCopy 實例,構造函數指定了目標數據庫,使用SqlBulkCopyOptions.UseInternalTransaction是指遷移動作指定在一個Transaction當中,如果數據遷移中產生錯誤或異常將發生回滾。
sbc.BulkCopyTimeout = 5000000; //指定操作完成的Timeout時間
sbc.SqlRowsCopied +=new SqlRowsCopiedEventHandler(OnRowsCopied);
sbc.NotifyAfter = dt.Rows.Count;
try
{
// sbc.DestinationTableName = "jobs";
sbc.DestinationTableName = "bcd";
sbc.WriteToServer(dt);
}
NotifyAfter 屬性指定通知通知事件前處理的數據行數,在這裡指定為表的行數,並添加SqlRowsCopied事件輸出整個遷移過程的時間。 WriteToServer方法就是將數據源拷備到目標數據庫。在使用WriteToServer方法之前必須先指定 DestinationTableName屬性,也就是目標數據庫的表名
性能方面:我在Sql中用proc插入68萬條數據花了近8分鐘,用SqlBulkCopy花了53.234秒~,效率高了7倍耶!不過現在也不做這方面的底層了,呵呵,把自己寫的一個測試存儲過程也貼上吧,方便自己學習
create table abc
(
aid int identity(1,1) primary key,
adesc varchar(50) not null
)
go
/**********存儲過程**********************/
create proc addData
as
declare @i int
set @i=1
while @i < 1000000
begin
insert into abc values ('testDescription')
set @i = @i + 1
end
go
select * into titles from pubs.dbo.titles where 1> 3 復制跨數據庫的表結構