在ASP.Net 2.0中提供了一個新的類SqlBulkCopy類,它在性能上的優勢更超過了上面的方法,它可以通過讓DataSet或是DataReader中大量的數據通過數據流直接進行裝載,然後可以將這些記錄添加到指定的數據表中。
SqlBulkCopy類只有在SQL Server的表中寫入數據,但在使用其它的數據庫時,可以通過數據源來使用,SqlBulkCopy類主要包括一個實例方法WriteToServer,它用來把數據從一個數據源傳輸到另外一個數據源。WriteToServer的方法可以快速的寫入DataRow[]數組數據,DataTable和DataReader。在實際開發的過程中,可以視情況而定,選擇我們所喜歡的方法,我們看它使用的方法:
WriteToServer(DataTable)寫入數據表
WriteToServer(DataRow[])批次寫入數據行
WriteToServer(DataTable,DataRowState)按行狀態寫入數據庫表
WriteToServer(DataReader)寫入DataReader對象
在多數情況下,我們選擇最好的方法是DataReader對象,因為DataReader是一個讀取只向前和只讀流的方式,所以它要比DataTable和DataRows[]更快,我們現在來看看下面的代碼,它用來把數據從一張表中傳輸到另一張表中。
代碼清單:
string strConnection = ConfigurationManager.APPSettings["conStr"].ToString();//讀取Web.config文件中的數據庫連接字符串
SqlConnection sourceconnection = new SqlConnection(strConnection);//數據的連接方式是SQL Server
sourceconnection.Open();//打開數據庫連接
SqlCommand cmd = new SqlCommand("Select * from MSreplication_options");//通過命令來讀取SQL語句
cmd.Connection = sourceconnection;//獲取連接方式
SqlDataReader reader = cmd.ExecuteReader();//開始執和結果集,獲取DataReader記錄集
//連接目標數據庫連接,並且打開數據庫連接方式,在此由於調用同一個數據庫,連接字符串沒有變
SqlConnection destinationConnection = new SqlConnection(strConnection);
destinationConnection.Open();
//調用SqlBulkCopy類的方法
SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnection);
//獲取目標表的名稱
bulkCopy.DestinationTableName = "destination";
//寫入DataReader對象
bulkCopy.WriteToServer(reader);
//關閉各個對象
reader.Close();
sourceconnection.Close();
destinationConnection.Close();
上例中,我們使用的是SQL Server 2005的master數據庫,我們在使用SqlBulkCopy的時候,需要了解一下它的幾個重要的屬性:
BatchSize:屬性的整數值;或者如果未設置任何值,則為零。每一批次中的行數。在每一批次結束時,將該批次中的行發送到服務器。
BulkCopyTimeOu:超時之前操作完成所允許的秒數。如果操作超時,事務便不會提交,而且所有已復制的行都會從目標表中移除。
ColumnMappings:返回 SqlBulkCopyColumnMapping 項的集合。列映射定義數據源中的列和目標表中的列之間的關系。如果數據源和目標表具有相同的列數,並且數據源中每個源列的序號位置匹配相應目標列的序號位置,則無需 ColumnMappings 集合。但是如果列計數不同,或序號位置不一致,則必須使用 ColumnMappings,以確保將數據復制到正確的列中。
DestinationTableName:指定的目標表中。
NotifyAfter:屬性的整數值,或者如果未設置該屬性,則為零。定義在生成通知事件之前要處理的行數。
在ColumnMappings屬性中,我們可以看到SqlBulkCopyColumnMapping 項,它主要是用來定義SqlBulkCopy實例的數據源中的列與該實例的目標表中的列之間的映射。
結合著上面SqlBulkCopy的屬性我們再來看一個綜合的例子,此例中我們使用DataTable:
在本例中,我先自己建立一個數據庫SqlBulkCopySample,然後建立一個表TblOrder,它主要是用來把Northwind數據庫中的Orders表數據全導進來,所以它的表結構基本上和Orders一樣,它們以應的關系如下:
ID (OrderID): int
Name (ShipName): nvarchar(40)
Address (ShipAddress): nvarchar(60)
City (ShipCity): nvarchar(15)
然後在Northwind數據中創建一個存儲過程,如下:
CREATE PROCEDURE dbo.SelectOrders
AS
SELECT OrderID, ShipName, ShipAddress, ShipCity
FROM Orders
我們在頁面中增加一個按鈕的點擊事件,當事件觸發的時候,執行的代碼如下:
private void btnStart_Click(object sender, EventArgs e)
{
String sourceConnectionString =
"Data Source=127.0.0.1;Initial Catalog=Northwind;Integrated Security=True";
String destinationConnectionString =
"Data Source=127.0.0.1;;Initial Catalog=SqlBulkCopySample;Integrated Security=True";
DataTable data = SelectDataFromSource(sourceConnectionString);//獲取數據
CopyDataToDestination(destinationConnectionString, data);//復制數據
}
獲取數據非常簡單,它只是通過執行存儲過程返回一個DataTable的查詢結果集,如下:
private DataTable SelectDataFromSource(String connectionString)
{
DataTable data = new DataTable();
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand("SelectOrders", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
data.Load(reader);
}
return data;
}
接著,就執行數據復制的操作,此部分的代碼為核心的部分,首先我們通過創建四個SqlBulkCopyColumnMapping對象,然後把兩個數據庫中的表之間的一一對應關系表述出來,然後設置好BatchSize及BulkCopyTimeout屬性,然後返回 SqlBulkCopyColumnMapping 項的集合,接著定義好目標表的名稱,以SqlRowsCopIEd事件處理程序,在定義在生成通知事件之前要處理的行數時,然後調用WriteToServer(DataTable) 方法寫入數據表,結束數據的復制,如下:
private void CopyDataToDestination(String connectionString, DataTable table)
{
SqlBulkCopyColumnMapping mapping1 =
new SqlBulkCopyColumnMapping("OrderID", "ID");
SqlBulkCopyColumnMapping mapping2 =
new SqlBulkCopyColumnMapping("ShipName", "Name");
SqlBulkCopyColumnMapping mapping3 =
new SqlBulkCopyColumnMapping("ShipAddress", "Address");
SqlBulkCopyColumnMapping mapping4 =
new SqlBulkCopyColumnMapping("ShipCity", "City");
SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString);
bulkCopy.BatchSize = 100;
bulkCopy.BulkCopyTimeout = 5;
bulkCopy.ColumnMappings.Add(mapping1);
bulkCopy.ColumnMappings.Add(mapping2);
bulkCopy.ColumnMappings.Add(mapping3);
bulkCopy.ColumnMappings.Add(mapping4);
bulkCopy.DestinationTableName = "tblOrder";
bulkCopy.SqlRowsCopIEd +=
new SqlRowsCopiedEventHandler(bulkCopy_SqlRowsCopIEd);
bulkCopy.NotifyAfter = 200;
bulkCopy.WriteToServer(table);
}
在bulkCopy_SqlRowsCopIEd的處理中,我只簡單的通過展現給用戶一個友好的提示信息讓你可以知道目前有多少行被復制成功。代碼如下:
private void bulkCopy_SqlRowsCopied(object sender, SqlRowsCopIEdEventArgs e)
{
MessageBox.Show
(String.Format("{0} Rows have been copied.", e.RowsCopIEd.ToString()));
}
這樣,在平時的開發中,我們可以靈活的在ASP.Net中使用SqlBulkCopy幫助我們復制大量的數據之間的數據源和數據表,並改善應用程序的性能。
獲取數據非常簡單,它只是通過執行存儲過程返回一個DataTable的查詢結果集,如下:
private DataTable SelectDataFromSource(String connectionString)
{
DataTable data = new DataTable();
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand("SelectOrders", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
data.Load(reader);
}
return data;
}
接著,就執行數據復制的操作,此部分的代碼為核心的部分,首先我們通過創建四個SqlBulkCopyColumnMapping對象,然後把兩個數據庫中的表之間的一一對應關系表述出來,然後設置好BatchSize及BulkCopyTimeout屬性,然後返回 SqlBulkCopyColumnMapping 項的集合,接著定義好目標表的名稱,以SqlRowsCopIEd事件處理程序,在定義在生成通知事件之前要處理的行數時,然後調用WriteToServer(DataTable) 方法寫入數據表,結束數據的復制,如下:
private void CopyDataToDestination(String connectionString, DataTable table)
{
SqlBulkCopyColumnMapping mapping1 =
new SqlBulkCopyColumnMapping("OrderID", "ID");
SqlBulkCopyColumnMapping mapping2 =
new SqlBulkCopyColumnMapping("ShipName", "Name");
SqlBulkCopyColumnMapping mapping3 =
new SqlBulkCopyColumnMapping("ShipAddress", "Address");
SqlBulkCopyColumnMapping mapping4 =
new SqlBulkCopyColumnMapping("ShipCity", "City");
SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString);
bulkCopy.BatchSize = 100;
bulkCopy.BulkCopyTimeout = 5;
bulkCopy.ColumnMappings.Add(mapping1);
bulkCopy.ColumnMappings.Add(mapping2);
bulkCopy.ColumnMappings.Add(mapping3);
bulkCopy.ColumnMappings.Add(mapping4);
bulkCopy.DestinationTableName = "tblOrder";
bulkCopy.SqlRowsCopIEd +=
new SqlRowsCopiedEventHandler(bulkCopy_SqlRowsCopIEd);
bulkCopy.NotifyAfter = 200;
bulkCopy.WriteToServer(table);
}
在bulkCopy_SqlRowsCopIEd的處理中,我只簡單的通過展現給用戶一個友好的提示信息讓你可以知道目前有多少行被復制成功。代碼如下:
private void bulkCopy_SqlRowsCopied(object sender, SqlRowsCopIEdEventArgs e)
{
MessageBox.Show
(String.Format("{0} Rows have been copied.", e.RowsCopIEd.ToString()));
}
這樣,在平時的開發中,我們可以靈活的在ASP.Net中使用SqlBulkCopy幫助我們復制大量的數據之間的數據源和數據表,並改善應用程序的性能。