C# Linq to XML此XML文件被读取了多少次?

C# Linq to XML此XML文件被读取了多少次?,c#,xml,asp.net-mvc,linq,linq-to-xml,C#,Xml,Asp.net Mvc,Linq,Linq To Xml,我的网站导航有一个类别的概念,这些类别包含描述、图像和与之相关的页面 在_ViewStart.cshtml中,我有以下LINQ查询,然后将结果存储在PageData中,因为我可能在给定页面上多次使用这些类别,并且不想重新运行查询 XDocument navigation = XDocument.Load(Server.MapPath("~/App_Data/Navigation.xml")); IEnumerable<Category> categories = from categ

我的网站导航有一个类别的概念,这些类别包含描述、图像和与之相关的页面

在_ViewStart.cshtml中,我有以下LINQ查询,然后将结果存储在PageData中,因为我可能在给定页面上多次使用这些类别,并且不想重新运行查询

XDocument navigation = XDocument.Load(Server.MapPath("~/App_Data/Navigation.xml"));
IEnumerable<Category> categories = from category in navigation.Root.Descendants("category")
                                   select new Category(
                                        category.Attribute("name").Value,
                                        category.Element("description").Value,
                                        new CategoryImage(
                                            category.Element("image").Element("path").Value,
                                            category.Element("image").Element("cssClass").Value,
                                            category.Element("image").Element("description").Value
                                        ),
                                        (from page in category.Descendants("page") select new BetterSolutions.ViewModels.ProductPage(page.Attribute("display").Value, page.Value)).ToList()
                                   );
PageData["categories"] = categories;
XDocument navigation=XDocument.Load(Server.MapPath(“~/App\u Data/navigation.xml”);
IEnumerable categories=来自navigation.Root.substands(“类别”)中的类别
选择新类别(
类别.属性(“名称”).值,
类别、要素(“说明”)、价值,
新分类图像(
类别。元素(“图像”)。元素(“路径”)。值,
类别.元素(“图像”).元素(“cssClass”).值,
类别.元素(“图像”).元素(“描述”).值
),
(从category.subjections(“页面”)的页面中选择new BetterSolutions.ViewModels.ProductPage(page.Attribute(“display”).Value,page.Value)).ToList()
);
PageData[“类别”]=类别;
当我通过调试器观察发生了什么时,每当我访问PageData[“categories”]时,它都会返回到_ViewStart.cshtml中的查询

当我通过在LINQ查询周围添加括号并在末尾添加.ToList()来更改上述代码时,它似乎执行了一次,然后再也不会执行


我应该怎么做?我认为添加.ToList()是正确的,因为查询似乎只运行了一次,但我可能误解了LINQ to XML中的延迟执行实际上是如何工作的。

看起来您忘记了对类别进行ToList()调用: 简单的解决办法是:

PageData["categories"] = categories.ToList();
我应该怎么做?我认为添加.ToList()是正确的,因为查询似乎只运行一次,但我可能误解了在LINQtoXML中延迟执行实际上是如何工作的

您看到的是延迟执行。当您创建
类别时,它不是项目的集合:它只是一个查询,需要结果时将执行该查询。该查询定义存储在
PageData[“categories”]
中。所以每次从那里开始,你必须执行它才能得到结果

添加
ToList()
会立即生成结果,因为您需要结果列表。然后,该列表存储在
PageData[“categories”]
中。这就是为什么您不必反复执行查询:因为您已经将结果存储在一个列表中,而且您甚至不知道以前的结果来自哪里

正确的方法是什么?视情况而定。如果您希望文件在
PageData[“categories”]
调用之间更改,并且需要它始终返回准确的结果,则可以使用当前的解决方案。如果文件未更改,或者可以不读取文件一次,并放弃在程序执行期间对文件所做的所有更改,则应使用
ToList()
使其性能更好,并避免不必要的文件访问

更新


我的主要答案并不完全正确。即使没有
ToList()
访问
PageData[“categories”]
也不会再次访问文件,因为文件已经完全加载并解析到
XDocument
实例中。但是它会遍历文档本身来执行查询。

他没有忘记-
我应该怎么做?我认为添加.ToList()是正确的,因为查询似乎只运行一次,但我可能误解了LINQ to XML中延迟执行的实际工作方式。
这是有道理的。当我创建类别时,C#知道查询结果将是IEnumerable吗?否则,我不应该在编译时出错吗?是的,输入查询以返回
Category
项的集合。
XDocument navigation = XDocument.Load(Server.MapPath("~/App_Data/Navigation.xml"));
IEnumerable<Category> categories = from category in navigation.Root.Descendants("category")
                                   select new Category(
                                        category.Attribute("name").Value,
                                        category.Element("description").Value,
                                        new CategoryImage(
                                            category.Element("image").Element("path").Value,
                                            category.Element("image").Element("cssClass").Value,
                                            category.Element("image").Element("description").Value
                                        ),
                                        (from page in category.Descendants("page") select new BetterSolutions.ViewModels.ProductPage(page.Attribute("display").Value, page.Value)).ToList()
                                   );
PageData["categories"] = categories;