2011-02-17 132 views
1

我正在將數據庫從MS Access移到sql server。爲了將數據移動到新表中,我決定編寫一個同步例程,因爲模式已經發生了很大的變化,它使我能夠對運行它的程序運行測試,並在需要新的測試數據時重新同步。然後最終我會做最後一次同步並開始在新的sql服務器版本上生效。SqlBulkCopy計算字段

不幸的是我遇到了阻礙,我的方法是下面複製從Access到SQLServer的

public static void BulkCopyAccessToSQLServer 
     (string sql, CommandType commandType, DBConnection sqlServerConnection, 
      string destinationTable, DBConnection accessConnection, int timeout) 
    { 
     using (DataTable dt = new DataTable()) 
     using (OleDbConnection conn = new OleDbConnection(GetConnection(accessConnection))) 
     using (OleDbCommand cmd = new OleDbCommand(sql, conn)) 
     using (OleDbDataAdapter adapter = new OleDbDataAdapter(cmd)) 
     { 
      cmd.CommandType = commandType; 
      cmd.Connection.Open(); 
      adapter.SelectCommand.CommandTimeout = timeout; 
      adapter.Fill(dt); 

      using (SqlConnection conn2 = new SqlConnection(GetConnection(sqlServerConnection))) 
      using (SqlBulkCopy copy = new SqlBulkCopy(conn2)) 
      { 
       conn2.Open(); 

       copy.DestinationTableName = destinationTable; 
       copy.BatchSize = 1000; 
       copy.BulkCopyTimeout = timeout; 
       copy.WriteToServer(dt); 
       copy.NotifyAfter = 1000; 
      } 
     } 
    } 

基本上這個查詢使用輸入SQL字符串這所有正確的字段名,所以我不要了數據訪問不需要設置列映射。

這是工作,直到我到達一個計算字段的表。 SQLBulkCopy似乎並不知道要跳過該字段並嘗試更新失敗的列,但出現錯誤「列'columnName'不能被修改,因爲它既可以是計算列,也可以是聯合運算符的結果。」

是否有一種簡單的方法可以使其跳過計算的字段?

我希望不必指定一個完整的列映射。

回答

5

有兩種方法來躲過此:

  • 使用ColumnMappings正式定義列關係(你注意到你不想要這個)
  • 推數據到臨時表 - 一個基本的表,不是你的核心事務表的一部分,它的全部目的是像一樣像這樣的數據導入;然後用T-SQL命令來將數據從臨時表中轉移到真正的表

我總是青睞有第二種選擇,因爲各種原因:

  • 我從來沒有與映射混亂 - 這是對我來說其實很重要,p
  • 插入到真正的表將被完全記錄(SqlBulkCopy一定登錄)
  • 我必須以最快的速度插入 - 沒有約束檢查,沒有索引,等等
  • 我不會在導入過程中綁定事務表,並且不存在針對部分導入的表運行不可重複查詢的風險
  • 如果導入失敗中途沒有,我有一個安全中止選項必須使用事務處理(此時什麼都沒有觸及事務系統)
  • 它將數據處理推入實際表時可以進行某種級別的數據處理,而不需要在應用層緩衝DataTable中的所有內容,或者實現自定義IDataReader
+1

而不是一個臨時表,我會建議一個可更新的視圖,只包括colu沒有計算的mns,然後批量複製到視圖中。 – 2016-04-23 15:01:08