【问题标题】:SqlBulkCopy - The given ColumnName does not match up with any column in the source or destinationSqlBulkCopy - 给定的 ColumnName 与源或目标中的任何列都不匹配
【发布时间】:2015-11-13 02:14:24
【问题描述】:

我正在尝试使用 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() 数据表,无需尝试使用纯字符串进行映射 全部。

【问题讨论】:

  • 什么是Global.SelectedColumns,它来自哪里/如何填充?我以为是DataGridView 中的SelectedColumns 属性,但它不返回字符串。
  • 这只是一个List<string> 填充列名。它是通过在数据库中查询所选表中的列列表并将其放入Global.AllColumns 列表来填充的,然后用户可以选择他们想要的那些,以对应于他们将打开的 CSV 文件的顺序应用程序。选择的列被复制到Global.SelectedColumns
  • 那是 exact 信息吗?它看起来不像我记得的......?
  • 还有,什么版本的SQL server?
  • 这是准确的消息,复制并粘贴。它是 2014 express,但这个应用程序将与各种版本一起使用。

标签: c# sql-server sqlbulkcopy


【解决方案1】:

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

我一直发现 ToString() 方法无论如何都是不稳定的(可以根据当前状态/条件进行更改),所以我建议改用 ColumnName 属性,因为这就是你真正想要得到的来自ToString()


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

【讨论】:

  • 感谢您的提示,我会更改它,但是我确定 .ToString() 不是这里的问题。这是不使用 .ToString() 的顶级方法不起作用。 DataColumn.ToString() 正在工作。
  • 不幸的是,这也不是。我已经直接从 SQL 中获取它们并用它们填充我的列表。
【解决方案2】:

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

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

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

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

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

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

【讨论】:

  • 用一个例子来说明这一点......我的插入失败,因为在列 [A] 的源中,我的值为“ABCD”,而映射的列 [A] 在目标中表是 char(2)。
猜你喜欢
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-09
  • 1970-01-01
相关资源
最近更新 更多