You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止SqlBulkCopy批量复制数据时修改XML列的字符串表示

问题根因说明

SQL Server的XML数据类型本身存储的是解析后的XML信息集(Infoset),不会保留原始字符串的非语义化格式差异,<Item></Item>和<Item/>语义完全等价,写入XML类型列时数据库会自动统一格式,该行为并非SqlBulkCopy主动修改导致。如果要求字符串表示完全一致,无法通过XML类型列实现,必须通过字符串类型存储原始XML内容。


适配方案(无需提前感知XML列,无需修改原有查询SQL)

你可以在adapter.Fill(table)之后,动态识别DataTable中的XML列并转换为字符串类型,完全不依赖前置的SQL生成逻辑,修改后的完整代码如下:

using (SqlDataAdapter adapter = new SqlDataAdapter(source_command))
{
    using (DataTable table = new DataTable())
    {
        adapter.Fill(table);

        // 新增逻辑:动态识别并转换XML列为字符串列
        List<DataColumn> xmlColumns = new List<DataColumn>();
        foreach (DataColumn col in table.Columns)
        {
            // DataTable读取SQL Server XML列的默认返回类型为XmlNode
            if (col.DataType == typeof(System.Xml.XmlNode))
            {
                xmlColumns.Add(col);
            }
        }
        foreach (var xmlCol in xmlColumns)
        {
            string tempColName = $"temp_{xmlCol.ColumnName}";
            // 新增字符串类型临时列存储原始XML字符串
            table.Columns.Add(tempColName, typeof(string));
            foreach (DataRow row in table.Rows)
            {
                if (row.IsNull(xmlCol))
                {
                    row[tempColName] = DBNull.Value;
                }
                else
                {
                    // OuterXml即为源库读取到的原始XML字符串
                    row[tempColName] = ((System.Xml.XmlNode)row[xmlCol]).OuterXml;
                }
            }
            // 替换原XML列为字符串列
            table.Columns.Remove(xmlCol);
            table.Columns[tempColName].ColumnName = xmlCol.ColumnName;
        }

        using (SqlConnection destination = new SqlConnection(destination_connectionstring))
        {
            destination.Open();

            using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destination, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls | SqlBulkCopyOptions.CheckConstraints, null))
            {
                bulkCopy.DestinationTableName = destination_table;
                bulkCopy.BulkCopyTimeout = 1200;

                foreach (DataColumn column in table.Columns)
                {
                    bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(column.ColumnName, column.ColumnName));
                }

                try
                {
                    bulkCopy.WriteToServer(table);
                }
                catch (Exception ex)
                {
                    Log.Logger.Error(ex.ToString());
                    throw;
                }
                finally
                {
                    table.Dispose();
                }
            }
        }
    }
}

注意事项

你需要提前将目标库对应表的XML列调整为nvarchar(max)类型,否则写入XML类型列时仍然会被数据库自动格式化,无法保留原始字符串格式。

内容的提问来源于stack exchange,提问作者Robert Wolf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 21:27:04