如何將數據導入到 SQL Server Compact Edition 數據庫中(四)

系列文章導航:
如何將數據導入到 SQL Server Compact Edition 數據庫中(一)
如何將數據導入到 SQL Server Compact Edition 數據庫中(二)
如何將數據導入到 SQL Server Compact Edition 數據庫中(三)

摘要:在本系列文章的第一篇和第二篇爲了提高數據寫入的性能,我使用了 SqlCeResultSet 基於表的數據寫入方式,而不是使用常規的 Insert 語句。使用 SqlCeResultSet 寫入數據確實方便又快速,但是必須保證從源數據庫查詢的結果集(通過 Select 查詢語句)跟目標數據庫(SQL Server Compact Edition)表的字段先後順序一致。如果不一致,可能會導致數據導入出錯;即便是導入成功,數據跟原來的字段位置也對不上。所以,我覺得有必要給大家介紹常規的 Insert 語句數據插入方式,解決 SqlCeResultSet 存在的問題。

在第三篇文章中,我們學習了 IDataReader.GetSchemaTable 方法,它可以返回一個描述了 DataReader 查詢結果中各列的元數據的 DataTable。在前面的文章介紹的數據導入方法中,都是使用 DataReader 從源數據庫讀取數據。那麼從這個 DataReader 獲取的 SchemaTable 信息,就可以用於生成插入數據的 Insert 語句,前提是源數據庫和目標數據庫的表字段名稱一致,字段的先後順序可以不一樣。以下是根據 SchemaTable 生成 Insert 語句的代碼:

// 通過 DataReader 獲取 SchemaTable 信息
srcReader = srcCommand.ExecuteReader(CommandBehavior.KeyInfo);
DataTable scheamTable 
= srcReader.GetSchemaTable();

// 生成 SQL Server Compact Edition 數據插入 SQL 語句
StringBuilder sbFields = new StringBuilder();
StringBuilder sbParams 
= new StringBuilder();
string field, param;
DataRow schemaRow;
for (int i = 0; i < scheamTable.Rows.Count; i++)
{
    
if (i != 0)
    {
        sbFields.Append(
"");
        sbParams.Append(
"");
    } 

    schemaRow 
= scheamTable.Rows[i];
    field 
= string.Format("[{0}]", schemaRow["ColumnName"]); //字段名稱
    param = "@" + ((string)schemaRow["ColumnName"]).Replace(" ""_"); //參數名稱
    sbFields.Append(field);
    sbParams.Append(param);
    destCommand.Parameters.Add(param, 
null);


string insertSql = string.Format("INSERT INTO [{0}]({1}) VALUES({2})", destTableName, sbFields, sbParams);
destCommand.CommandText 
= insertSql; 

生成 Insert 語句的代碼很簡單,這裏就不再詳細說明了。準備好了 Insert 語句,就可以開始從源數據庫取數據並寫入目標數據庫了。這裏我使用了 DataReader.GetValues 方法一次性讀取一整行數據,再給 Insert 命令的參數賦值。代碼如下所示:

// 執行數據導入
object[] values;
while (srcReader.Read())
{
    values 
= new object[srcReader.FieldCount];
    srcReader.GetValues(values);
    
for (int i = 0; i < values.Length; i++)
    {
        destCommand.Parameters[i].Value 
= values[i];
    }
    destCommand.ExecuteNonQuery();
}

本文的主要內容到這裏已經介紹完了,我們可以結合第三篇文章介紹的根據 SchemaTable 自動生成創建表結構的 SQL 語句的代碼,在導入數據前先自動創建數據表結構。相關的代碼如下:

// 通過 DataReader 獲取 SchemaTable 信息
srcReader = srcCommand.ExecuteReader(CommandBehavior.KeyInfo);
DataTable scheamTable = srcReader.GetSchemaTable();


// 創建 SQL Server Compact Edition 表結構
SqlCeCommand command = destConnection.CreateCommand();
command.CommandText 
= GenerateTableSchemaSql(scheamTable);
command.ExecuteNonQuery();

// 生成 SQL Server Compact Edition 數據插入 SQL 語句
StringBuilder sbFields = new StringBuilder();
StringBuilder sbParams = new StringBuilder();
......

通過遍歷 SQL Server 2000 的 Northwind 數據庫的每個用戶表,並將每個表的數據導入到一個 SQL Server Compact Edition 數據文件 Northwind.sdf 中。代碼如下所示:

// 創建源 SQL Server 數據庫連接對象
string srcConnString = "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True";
SqlConnection srcConnection 
= new SqlConnection(srcConnString);

// 創建目標 SQL Server Compact Edition 數據庫連接對象
string destConnString = @"Data Source=C:/Northwind.sdf";
SqlCeConnection destConnection 
= new SqlCeConnection(destConnString);

// 創建 SQL Server Compact Edition 數據文件
VerifyDatabaseExists(destConnString);

srcConnection.Open();
destConnection.Open();

// 複製數據
string[] tableNames = GetTableNames(srcConnection);
string query;
for (int i = 0; i < tableNames.Length; i++)
{
    query 
= string.Format("SELECT * FROM [{0}]", tableNames[i]);
    CopyTable(srcConnection, destConnection, query, tableNames[i]);
}

srcConnection.Close();
destConnection.Close();

同第二篇文章相比,本文中的 VerifyDatabaseExists 方法只創建 SQL Server Compact Edition 數據文件,不批量創建表結構,因爲我們用上了“自動”的方法,不需要預先準備好創建表結構的 SQL 腳本。GetTableNames 和 GenerateTableSchemaSql 方法跟第三篇文章的一樣,這裏不再解釋。

總結:本文介紹了一種比 SqlCeResultSet 更安全的數據寫入方式,並結合了第三篇文章中介紹的自動生成創建數據庫表結構的 SQL 語句的方法,向大家展示了一種比較完善的 SQL Server Compact Edition 數據導入方法。在後續的文章中我會繼續深入下去,提供本方案在實際應用中面臨的問題的解決方法。

示例代碼下載:sqlce_data_import4.rar

作者:黎波
博客:http://upto.cnblogs.com/
日期:2008年2月9日

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章