C# 逐个记录验证XML记录并将其提取到数据库中

C# 逐个记录验证XML记录并将其提取到数据库中,c#,.net,xml,linq,linq-to-xml,C#,.net,Xml,Linq,Linq To Xml,事情是这样的。我有一个包含大量记录的XML文档。大概是这样的: print("<?xml version="1.0" encoding="utf-8" ?> <Orders> <Order> <Phone>1254</Phone> <City>City1</City> <State>State</State>

事情是这样的。我有一个包含大量记录的XML文档。大概是这样的:

print("<?xml version="1.0" encoding="utf-8" ?>
      <Orders>
       <Order>
         <Phone>1254</Phone>
         <City>City1</City>
      <State>State</State>
      </Order>
      <Order>
         <Phone>98764321</Phone>
         <City>City2</City>
        <State>State2</State>
      </Order>  
     </Orders>");
打印(“
1254
城市1
陈述
98764321
城市2
状态2
");

还有一个XSD模式文件。我想从这个文件中提取数据,并将这些记录插入到数据库表中。首先,我当然想验证每个订单记录。例如,如果文件中有5个订单,其中2个未通过验证,我想将通过验证的3个订单插入数据库,剩下2个。一个xml文件中可以有数千条记录。这里最好的方法是什么。既然我需要丢弃失败的记录,只使用通过验证的记录,那么验证将如何进行呢。目前,我正在使用XmlReaderSettings来验证XML文档记录。在插入数据库之前,我应该将这些记录提取到另一个XML文件、数据集或自定义对象中吗。我正在使用.NET3.5。欢迎使用任何代码或链接。

如果数据相当清晰地映射到对象模型,您可以尝试使用xsd.exe从.xsd生成一些类,并将这些类处理到您选择的DAL中。问题是,如果数量很大(你提到了数千条记录),你很可能会有很多往返


另一种选择可能是将数据“按原样”传递到数据库,并使用SQL/XML在TSQL中处理数据——可能是作为接受XML类型参数的存储过程(SQL Server 2005等)。

这在很大程度上取决于“验证”在场景中的含义。我假设,由于您使用的是.xsd,您已经在验证数据的语法是否正确。 所以,验证可能意味着您将调用其他服务或过程来确定订单是否有效

您可能想看看Sql Server集成服务。SSIS中的XML任务允许您执行诸如XPath查询、合并、可能的任何操作以及需要对该文档执行的所有操作。您还可以使用该方法对模式文件进行所有前期验证


Marc将数据传递给存储过程的选项在这种情况下也可能起作用,但是SSI(或者,甚至是DTS,但您将放弃太多与XML相关的内容,使其成为一个不错的选项)将让您可视化地协调所有这项工作。另外,这将使这些东西更容易在过程之外运行,因此您最终应该得到一个更具可扩展性的解决方案。

您有两个选择:

  • 或者。这种方法的缺点是数据将被缓存在内存中,如果数据太多,这是不好的。另一方面,您可以使用DataSet获得良好的内存查询功能。XmlDocument要求您使用XPath查询来处理数据,而XmlDataDocument为您提供了更像数据集功能的体验

  • 。这是一个好的、快速的方法,因为数据没有被缓存;你一次读一点,就像一条小溪。您可以从一个元素移动到下一个元素,并在应用程序中查询有关该元素的信息,以决定如何处理该元素。这确实意味着您要在应用程序的内存中维护您所处的树级别,但是对于像您这样的简单XML文件结构,这应该非常简单


  • 我建议在你的情况下选择2。它应该在内存使用方面具有良好的扩展性,并且应该为处理文件提供最简单的实现。

    通过验证,我指的是验证每个节点。至少有一个错误的节点需要插入到新的xml文档中。基本上,最后我应该有2个xml文档。一个包含成功节点,另一个包含失败节点。我有什么办法可以做到吗?我正在使用LINQ。

    我同意您应该使用XmlReader的想法,但我想我应该尝试一些不同的东西

    基本上,我首先验证整个XDocument,然后如果有错误,我将枚举订单,并根据需要将其装箱。这并不漂亮,但也许会给你一些想法

            XDocument doc = XDocument.Load("sample.xml");
            XmlSchemaSet schemas = new XmlSchemaSet();
            schemas.Add("", "sample.xsd");
    
            bool errors = false;
            doc.Validate(schemas, (sender, e) =>
            {
                errors = true;
            });
    
            List<XElement> good = new List<XElement>();
            List<XElement> bad = new List<XElement>();
            var orders = doc.Descendants("Order");
            if (errors)
            {
                foreach (var order in orders)
                {
                    errors = false;
                    order.Validate(order.GetSchemaInfo().SchemaElement, schemas, (sender, e) =>
                    {
                        errors = true;
                    });
    
                    if (errors)
                        bad.Add(order);
                    else
                        good.Add(order);
                }
            }
            else
            {
                good = orders.ToList();
            }
    
    XDocument doc=XDocument.Load(“sample.xml”);
    XmlSchemaSet schemase=新的XmlSchemaSet();
    schemas.Add(“,”sample.xsd“);
    布尔误差=假;
    文档验证(模式,(发送方,e)=>
    {
    错误=正确;
    });
    List good=新列表();
    List bad=新列表();
    风险值订单=单据子体(“订单”);
    如果(错误)
    {
    foreach(订单中的var订单)
    {
    错误=错误;
    order.Validate(order.GetSchemaInfo().SchemaElement,模式,(发送方,e)=>
    {
    错误=正确;
    });
    如果(错误)
    坏。添加(订单);
    其他的
    好,添加(订单);
    }
    }
    其他的
    {
    good=命令。ToList();
    }
    
    您可以使用一个公共函数代替lambda表达式,但我只是将其组合在一起。此外,您可以构建两个XDocument,而不是将order元素推送到一个列表中。我肯定这里还有很多其他的问题,但也许这会引发一些问题