SqlBulkCopy计算字段

时间:2011-02-17 12:42:22

标签: c# .net sql-server ms-access sqlbulkcopy

我正在努力将数据库从MS Access移动到sql server。为了将数据移动到新表中,我决定编写一个同步例程,因为模式已经发生了很大变化,它允许我对运行它的程序运行测试,并在需要新的测试数据时重新同步。然后最终我将进行最后一次同步并在新的sql server版本上启动。

不幸的是我遇到了麻烦,我的方法是从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字符串查询数据的访问权限,这具有所有正确的字段名称,因此我不需要设置columnmappings。

这一直有效,直到我到达一个带有计算字段的表格。 SQLBulkCopy似乎不知道跳过该字段并尝试更新失败的列,并显示错误“列'columnName'无法修改,因为它是计算列或者是union运算符的结果。”

是否有一种简单的方法可以跳过计算字段?

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

1 个答案:

答案 0 :(得分:6)

有两种方法可以避免这种情况:

  • 使用ColumnMappings正式定义列关系(您注意到您不希望这样)
  • 将数据推送到临时表 - 一个基本表,而不是核心事务表的一部分,其完整目的是像这样的数据导入一样完全;然后使用TSQL命令将数据从登台表传输到真实表

由于各种原因,我总是赞成第二种选择:

  • 我永远不必乱用映射 - 这对我来说非常重要; p
  • 将完全记录对真实表的插入(SqlBulkCopy 必须记录)
  • 我有最快的插入 - 没有约束检查,没有索引等
  • 导入期间我没有占用事务表,并且不存在针对部分导入的表运行不可重复查询的风险
  • 如果导入失败一半,我有一个安全的中止选项,而不必使用事务(此时没有任何事情触及事务系统)
  • 在将其推送到真实表格时允许某种程度的数据处理,而无需缓冲应用层DataTable中的所有内容,或实现自定义IDataReader