【问题标题】:Linq to Xml: Is XDocument a caching reader?Linq to Xml:XDocument 是缓存读取器吗?
【发布时间】:2013-10-18 10:59:05
【问题描述】:

我喜欢 Linq to Xml API。我用过的最简单的一个。

我还记得它是在XmlReader 之上实现的,这是一个非缓存读取器,意思是:

var rdr = XmlReader.Create("path/to/huge_3Gb.xml");

...将立即返回(可能最多读取 xml 标头)。

XDocument.Load()documentation 表明它确实使用了XmlReader.Create()

我希望,就像所有 Linq 一样,我会使用 Linq2Xml 获得延迟执行行为。
但是后来我尝试了这个,就像我通常对涉及文件的任何事情一样:

using(var xdoc = XDocument.Load("file")){ ... }

还有惊喜!它不能编译,因为 XDocument 没有实现 IDisposable!

嗯,这很奇怪!当我使用完XDocument 后,我将如何永远释放文件句柄?

然后我恍然大悟:也许XDocument.Load() 会立即吃掉内存中的整个 Xml(并立即关闭文件句柄)?

所以我尝试了:

var xdoc = XDocument.Load("path/to/huge_3Gb.xml");

等待,等待,然后进程说:

Unhandled Exception: OutOfMemoryException.

所以 Linq to Xml 接近完美(很棒的 AP​​I),但没有雪茄(在大型 Xml 上使用时)。

</rant>

我的问题是:

  1. 我是否遗漏了什么,有一种方法可以懒惰地使用 Linq to Xml?

  2. 如果上一个问题的答案是“否”:

Linq to Xml API 不能具有类似于 Linq to Objects 的延迟行为是否有客观原因?在我看来,至少某些操作(例如,仅转发 XmlReader 可能实现的事情)可以延迟实现。

...或者是不是这样实现的,引用Eric Lippert

" 因为从来没有人设计、指定、实施、测试过, 记录并发布了该功能”?

【问题讨论】:

    标签: c# xml linq linq-to-xml


    【解决方案1】:

    实际上 Linq to Xml 使用延迟执行。但它查询内存中的数据,而不是文件中的数据。您可以从文件、流、字符串或手动构建文档中加载数据 - 内存中节点图的构建方式无关紧要。 Linq to xml 用于查询 xml 树(即对象图)的内存表示。

    这是一个示例,它显示了延迟执行如何与 Linq to Xml 一起工作。假设您有 XDocument,其中包含具有以下数据的对象图:

    <movies>
      <movie id="1" name="Avatar"/>
      <movie id="2" name="Doctor Who"/>
    </movies>
    

    如何创建此 xml 数据的内存表示并不重要。例如

     var xdoc = XDocument.Parse(xml_string);
     // or XDocument.Load(file_name);
     // or new XDocument(new XElement("movies"), ...)
    

    现在定义查询:

    var query = xdoc.Descendants("movie");
    

    您可以修改内存中的 xml 表示,该文档包含:

    xdoc.Root.Add(new XElement("movie"), new XAttribute("id", 3));
    

    现在执行查询:

    int moviesCount = query.Count(); // returns 3
    

    如您所见,Linq to Xml 使用延迟执行,但它的工作方式类似于 Linq to Objects - 在这里查询内存中的数据。

    注意:XDocument 没有实现 IDisposable,因为它在节点图构建后不持有任何非托管资源。

    【讨论】:

    • 很好的解释。我只是希望这种懒惰的行为会一直渗透到提供者身上。这是“浅层”延迟执行,对大文件没有多大帮助。
    • @CristiDiaconescu 这就是 Linq to Xml 的工作方式 - 您首先需要创建文档(即读取文件),然后才能查询它。 Linq to Xml 需要内存中的所有数据,与旧的 XmlDocument 完全相同。所以,海量数据并不好。实际上,我认为 Xml 文件不适合存储大量数据。通常在这种情况下使用数据库。
    猜你喜欢
    • 1970-01-01
    • 2013-08-07
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多