SqlBulkCopy - 给定的ColumnName与源或目标中的任何列都不匹配

时间:2015-08-19 16:46:58

标签: c# sql-server sqlbulkcopy

我正在尝试使用SqlBulkCopy将数据复制到SQL数据库表中,但是(错误地)说列不匹配。他们匹配。如果我使用断点来查看要映射的列的名称,它们是正确的。错误消息显示列的名称,它是正确的。

这是我的方法。我有一个 工作的相同方法,唯一的区别是它从哪里获取列名。但是,包含列名的字符串完全相同。

    public static bool ManualMapImport(DataTable dataTable, string table)
    {
        if(dataTable != null)
        {
            SqlConnection connection = new SqlConnection(connectionString);
            SqlBulkCopy import = new SqlBulkCopy(connection);
            import.DestinationTableName = "[" + table + "]";
            foreach (string s in Global.SelectedColumns)
            {                    
            /* The s string variable here is the EXACT same as
               the c.ToString() in the other method below */

                if (ColumnExists(table, s))
                    import.ColumnMappings.Add(s, s); 
                else
                    return false;
            }

            connection.Open();
            import.WriteToServer(dataTable); //Error happens on this line
            connection.Close();

            return true;
        }
        else
        {
            return false;
        }
    }

这是几乎相同的工作方法:

    public static bool AutoMapImport(DataTable dataTable, string table)
    {
        if (dataTable != null)
        {
            SqlConnection connection = new SqlConnection(connectionString);
            SqlBulkCopy import = new SqlBulkCopy(connection);
            import.DestinationTableName = "[" + table + "]";           
            foreach (DataColumn c in dataTable.Columns)
            {
                if (ColumnExists(table, c.ToString()))
                    import.ColumnMappings.Add(c.ToString(), c.ToString());
                else
                    return false;
            }

            connection.Open();
            import.WriteToServer(dataTable);
            connection.Close();

            return true;
        }
        else
        {
            return false;
        }
    }

如果有帮助,列名称为:ACT_Code,ACT_Paid,ACT_Name,ACT_Terminal_Code,ACT_TCustom1,ACT_TCustom2。这些在数据库本身完全相同。我知道SqlBulkCopy映射区分大小写,并且列名确实是正确的。

这是错误消息:

  

类型'System.InvalidOperationException'的未处理异常   发生在System.Data.dll

中      

其他信息:给定的ColumnName'ACT_Code'不匹配   使用数据源中的任何列。

希望我在这里错过了一些明显的东西,但我很好,真的迷失了。

非常感谢。

  编辑:对于遇到与我有同样问题的人来说,这是怎么回事   我修好了它。

     

而不是让ManualMapImport()方法成为近乎克隆的   AutoMapImport(),我让它循环遍历数据表的列   并更改名称,然后调整AutoMapImport()   数据表,无需尝试使用普通字符串进行映射   所有

2 个答案:

答案 0 :(得分:3)

根据MSDN(here),DataColumn.ToString()方法返回“表达式值,如果设置了属性;否则,返回ColumnName属性。”。

我总是发现ToString()方法无论如何都可以改变(可以根据当前状态/条件进行更改),因此我建议使用ColumnName属性,因为这就是你的意思实际上试图摆脱ToString()

好的,如果失败了,那么我必须猜测这是源数据表中列的名称区分大小写的问题,因为SQLBulkCopy 非常区分大小写,即使SQL DB不是。为了解决这个问题,我想说当你检查该列是否存在时,你应该返回/使用数据表列列表本身的实际字符串,而不是使用传入的任何字符串。这应该能够修复您的ColumnsExist例程可能忽略的任何大小写或重音差异。

答案 1 :(得分:0)

我遇到了同样的问题......这条消息可能看起来有点误导,因为它表明你没有执行正确的映射。

为了找到问题的根源,我决定一步一步地添加表格列并调用WriteToServer方法。

假设您有一个有效的列映射,您必须确保源DataTable和目标表之间的以下内容:

  • 列类型和长度(!)匹配
  • 您已为每个非空(NOT NULL)目标列提供了有效值

如果您不控制您的标识列值并希望SQL Server为您完成此任务,请确保指定SqlBulkCopyOptions.KeepIdentity选项。在这种情况下,您不会将标识列添加到源。

这应该是您的批量插入工作的全部内容。希望它有所帮助。