Linq对性能问题需要花费更多时间

时间:2011-09-15 07:16:10

标签: c# xml linq

我有一个基于对象值更新的xml代码。这里的'foreach'循环花了大约12-15分钟来获取一个200 kb的xml文件。请建议我如何提高性能。 (xml文件包含一个四级标记,其中子级(第4级)标记的数量均为10个)

代码:

IEnumerable<XElement> elements = xmlDoc.Descendants();
foreach (DataSource Data in DataLst)
{ 
    XElement xmlElem = (from xmlData in elements
                        where Data.Name == xmlData.Name.LocalName  //Name
                           && Data.Store == xmlData.Element(XName.Get("Store", "")).Value
                           && Data.Section == xmlData.Element(XName.Get("Section", "")).Value
                        select xmlData.Element(XName.Get("Val", ""))).Single();

    xmlElem.ReplaceWith(new XElement(XName.Get("Val", ""), Data.Value));
} 

7 个答案:

答案 0 :(得分:2)

这里看起来你有一个O(n)×O(m)问题,因为n = DataList的大小,m = xml的大小。要使这个O(n)+ O(m),你应该索引数据;例如:

var lookup = elements.ToLookup(
       x => new {
            Name = x.Name.LocalName,
            Store = x.Element(XName.Get("Store", "")).Value,
            Section =  x.Element(XName.Get("Section", "")).Value},
       x =>  x.Element(XName.Get("Val", ""))
    );

foreach (DataSource Data in DataLst)
{ 
    XElement xmlElem = lookup[
          new {Data.Name, Data.Store, Data.Section}].Single();
    xmlElem.ReplaceWith(new XElement(XName.Get("Val", ""), Data.Value));
}

(未经测试 - 仅显示一般方法)

答案 1 :(得分:1)

我认为更好的方法是将XML反序列化为C#类,然后使用LINQ,应该很快。

答案 2 :(得分:0)

如果真的需要很长时间来运行它,那么可能会这样做:

  1. 不要同时迭代 - 只迭代XML-File并从DataLst加载数据(创建一个SQL命令或简单的linq语句来加载基于Name / Store / Section的数据),制作一个简单的结构/ class为您的密钥与此数据(名称/商店/部分) - 不要忘记实现equals和GetHashCode
  2. 遍历您的XML-Elements并使用字典查找要替换的值
  3. 这样,您只需为DataSource中的每个数据迭代一次XML文件。

答案 3 :(得分:0)

目前尚不清楚为什么要花那么长时间 - 这是非常很长时间。 DataLst中有多少元素?我会尽快重写查询以简化:

IEnumerable<XElement> elements = xmlDoc.Descendants();
foreach (DataSource data in DataLst)
{ 
    XElement valElement = (from element in xmlDoc.Descendants(data.Name)
                           where data.Store == element.Element("Store").Value
                              && data.Section == element.Element("Section").Value
                           select element.Element("Val")).Single();

    valElement.ReplaceWith(new XElement("Val"), data.Value));
} 

(顺便说一句,我假设你的元素实际都没有名称空间。)

接下来:考虑替换valElement内容,而不是替换元素本身。将其更改为:

valElement.ReplaceAll(data.Value);

现在,这一直都在努力保持避免预计算等的简单性......因为它听起来就好像不应该花这么长时间。但是,可能需要像Marc和Carsten建议的那样构建查找。

答案 4 :(得分:0)

尝试将LINQ中的Single()调用替换为First()

答案 5 :(得分:0)

冒着火焰的危险,你考虑过用XQuery写这个吗?一个体面的XQuery处理器很可能会有一个连接优化器来有效地处理这个查询。

答案 6 :(得分:0)

“非常感谢大家的宝贵时间和精力”

问题答案:实际上,对象'DataLst'的类型为IEnumerable&lt;&gt;花了很多时间来获取值,但在我将其更改为List&lt;&gt;之后键入性能大幅提升(现在在20秒内运行)