Linq到Xml,保持XDocument加载?

假设我正在制作一个WinForms程序,它将在幕后使用XML文档作为持久性机制……

以下两种方法的优缺点是什么?

  1. 在每个方法调用中加载XDocument:

    public class XmlFoosRepository { string xmlFileName; public XmlFoosRepository(string xmlFileName) { this.xmlFileName = xmlFileName; } public int AddFoo(Foo foo) { var xDoc = XDocument.Load(xmlFileName); // Always call Load() // ... xDoc.Save(xmlFileName); return foo.ID; } public IEnumerable<Foo> GetFoos() { var xDoc = XDocument.Load(xmlFileName); // Always call Load() // ... return foos; } } 

要么

  1. 将XDocument保留在内存中……

     public class XmlFoosRepository { XDocument xDoc; public XmlFoosRepository(string xmlFileName) { xDoc = XDocument.Load(xmlFileName); // Now in memory } public int AddFoo(Foo foo) { // ... xDoc.Save(xmlFileName); return foo.ID; } public IEnumerable<Foo> GetFoos() { // ... return foos; } } 

第一个似乎效率稍低,因为每次访问XML文档时都无法获得任何结果。 使用选项1,您必须转到磁盘,并在访问之前将XML文件加载到内存中。 转到磁盘是您可以使用现代计算机执行的最昂贵的操作之一,应尽可能避免。

话虽这么说,如果XML文件太大,内存占用量非常大,那么你可能只希望在很短的时间内加载它。 但是,如果内存占用量很大,那么您可能希望查看另一种持久化数据的方法,这种方法不需要您一次加载整个文档来进行修改。

平衡主要是在内存和文件系统访问之间 – 如果您要在代码中大量使用文档,那么您不希望与文件系统进行更多的交互…但是如果它很少被访问而且很大,你可能不希望记忆命中。

我可能会默认将它保留在内存中 – 当它变得足够大以至于内存命中很重要时,你可能不想使用XML。

除了这些方面,在这两种情况下,您都需要考虑特定应用程序所需的线程模型。

就像一个数据点 – 我在深度网站的C#中使用第二个模式进行勘误表等,它运行得非常好。

将文档存储在内存中的一个可能的缺点是,如果您没有降级缓存,那么这些实例将永远存在。 这不一定是一件可怕的事情,但这是你应该在设计中考虑的事情。

此外,缓存中的项目数,如果文档很大,或者您有大量的小文档,可能会导致内存问题。 同样,您必须衡量这是否是您的关注点。

也就是说,你肯定从缓存中获益; 根据文档以及访问它的频率,您不必重复处理文档到XDocument 。 如果文档很大,或者您多次访问它们,那么您可以节省一次处理时间,而不必再次执行。

基于文件的优点: – 跨进程工作良好(如果需要) – 保持持续的内存需求小(如果文件很大,如超过10mb)基于文件的缺点: – 加载每个操作较慢

基于内存的优点: – 更快,没有一次又一次重新序列化的开销 – 更容易移植,如果您以后需要通过Web服务访问该文件,等等。基于内存的缺点: – 正在进行的内存要求(如果是大文件) )

另一个想法是,如果你已经有了XML数据,那么为什么不将它用作POCO对象,而是将它们重新序列化为“GetFoos”方法中的对象。