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

C#提取XML嵌套节点遍历所有订单行批量插入SQL的问题

代码问题修正方案

核心问题定位

  • 遍历逻辑缺失:当前代码通过FirstOrDefault()只取了OrderLineCollection下第一个OrderLine节点的ProductCode,没有对所有订单行节点做循环处理,因此只会插入第一条产品数据。
  • 节点路径匹配错误:提取Type字段(对应XML中的DocketSubType)时,代码错误查找了不存在的Type节点,实际XML中对应路径为Order/DocketSubType/Code,该字段值实际永远为空。
  • SQL传参逻辑缺失:原有拼接的SQL语句没有传入ProductCode参数,即使拿到了所有产品编码也无法写入数据库。
  • 路径写法冗余:XDocument加载完成后,Root属性已经对应最外层的UniversalShipment节点,从xmlDocument下再嵌套查找UniversalShipment属于多写了一层无效路径。
  • SQL拼接存在风险:通过字符串拼接生成SQL的方式,遇到字段值包含单引号、特殊字符会直接报错,且存在SQL注入隐患,需要替换为参数化查询。

修正后的可运行逻辑

1. 提取订单公共字段

先定位节点路径,提取所有与具体订单行无关的公共字段(这些字段在同一张订单的所有行中值完全一致,只需提取一次):

// 直接从根节点定位Shipment、Order,避免冗余长路径
XElement shipmentNode = xmlDocument.Root.Element(ns + "Shipment");
XElement orderNode = shipmentNode?.Element(ns + "Order");
// 定位对应类型的Client节点
XElement clientNode = shipmentNode.Descendants(ns + "OrganizationAddress")
    .FirstOrDefault(x => x.Element(ns + "AddressType")?.Value == "SendersLocalClient");

// 提取公共字段
string client = clientNode?.Element(ns + "CompanyName")?.Value;
string warehouse = orderNode?.Element(ns + "Warehouse")?.Element(ns + "Name")?.Value;
string orderReference = orderNode?.Element(ns + "OrderNumber")?.Value;
string customerReference = orderNode?.Element(ns + "ClientReference")?.Value;
string orderType = orderNode?.Element(ns + "DocketSubType")?.Element(ns + "Code")?.Value;

2. 循环遍历所有订单行完成插入

所有订单行共用同一个数据库连接,避免重复打开/关闭连接的性能损耗,逐行提取ProductCode并传参插入:

// 获取所有订单行节点,为空时返回空集合避免空引用报错
IEnumerable<XElement> orderLineNodes = orderNode?.Element(ns + "OrderLineCollection")
    ?.Elements(ns + "OrderLine") ?? Enumerable.Empty<XElement>();

string connectionString = "Data Source=My Server;Initial Catalog=MyDB;User ID=MyUser;Password=MyPassword";
// using语法自动释放数据库连接资源
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    // 提前初始化命令对象,循环内只改参数值,不重复新建命令
    using (SqlCommand command = new SqlCommand("InsertXML", connection))
    {
        command.CommandType = CommandType.StoredProcedure;
        // 绑定存储过程参数
        command.Parameters.Add("@Client", SqlDbType.NVarChar, 100);
        command.Parameters.Add("@Warehouse", SqlDbType.NVarChar, 100);
        command.Parameters.Add("@OrderReference", SqlDbType.NVarChar, 50);
        command.Parameters.Add("@CustomerReference", SqlDbType.NVarChar, 50);
        command.Parameters.Add("@Type", SqlDbType.NVarChar, 50);
        command.Parameters.Add("@ProductCode", SqlDbType.NVarChar, 50);

        // 逐行遍历订单行
        foreach (XElement line in orderLineNodes)
        {
            string productCode = line.Element(ns + "Product")?.Element(ns + "Code")?.Value;
            if (string.IsNullOrEmpty(productCode)) continue; // 跳过无效空行

            // 给参数赋值
            command.Parameters["@Client"].Value = client;
            command.Parameters["@Warehouse"].Value = warehouse;
            command.Parameters["@OrderReference"].Value = orderReference;
            command.Parameters["@CustomerReference"].Value = customerReference;
            command.Parameters["@Type"].Value = orderType;
            command.Parameters["@ProductCode"].Value = productCode;

            // 执行插入
            command.ExecuteNonQuery();
        }
    }
}

批量处理文件夹下上千个XML的扩展方法

后续扩展批量能力时,只需在最外层增加文件遍历逻辑即可:

  • 用Directory.EnumerateFiles("你的XML文件夹路径", "*.xml")拿到所有XML文件的完整路径
  • 对每个文件加载XDocument,执行上述提取、插入逻辑
  • 增加基础异常捕获,遇到损坏、格式不符的XML文件跳过处理,不中断整体批量流程

内容的提问来源于stack exchange,提问作者Seb Soum

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 16:06:05