C# IEnumerable 访问后清空
C# IEnumerable Emptied Once Accessed
我正在建立一个 Umbraco 8 网站并且 运行 遇到了一些奇怪的行为。该项目正在使用.NET 4.7.2。
基本上,我有一个 Event
类型的 IENumerable,这是一个简单的内容列表,我想将其呈现到列表中。但是,每当我对列表(包含项目)执行任何操作时,列表都会立即清空。这包括简单地分配给不同的变量,检查 null 等。
我不认为这是 Umbraco 8 的问题,但为了清楚起见,我目前正在 运行 通过 Surface Controller 并通过在我的视图中调用以下命令来渲染它:
@Html.Action("RenderUpcoming", "Events")
这是控制器:
using Index.Models.Events;
using Index.Models.PublishedContent;
using Papermoon.Umbraco.Kupo.Core.Services.Interfaces;
using System;
using System.Linq;
using System.Web.Mvc;
using Umbraco.Web.Mvc;
namespace Index.Web.Controllers.Surface
{
public class EventsController : SurfaceController
{
private readonly KupoGeneralSettings _kupoGeneralSettings;
public EventsController(IKupoSettingsService kupoSettingsService)
{
_kupoGeneralSettings = kupoSettingsService.GetSettings<KupoGeneralSettings>("kupoGeneralSettings");
}
public ActionResult RenderUpcoming()
{
UpcomingEventsModel model = new UpcomingEventsModel();
model.Title = "Upcoming Events";
model.Events = Umbraco.ContentAtXPath("root/homepage/events/event").Select(x => new Event(x));
model.Events = model.Events.Where(x => x.StartDate > DateTime.Now).OrderBy(x => x.StartDate).Take(3);
model.TotalEvents = model.Events.Count();
model.EventListingLink = _kupoGeneralSettings.EventListingLink;
return PartialView("~/Views/Partials/Events/UpcomingEvents.cshtml", model);
}
}
}
所以在这里,当我调用 model.Events = model.Events.Where(x => x.StartDate > DateTime.Now).OrderBy(x => x.StartDate).Take(3);
- 我有结果,然后当我调用 model.TotalEvents = model.Events.Count();
时,列表 (model.Events) 是空的。
当我分配给另一个变量时,当我调用 model.Events.Any()
时,甚至当我执行 Model.Events != null
.
时,也会发生这种情况
展示这件事可能比说出来更容易,所以请看随附的 gif 动图:https://i.imgur.com/rE3VAqe.gif
谢谢,
本
当然 – 你不知道对象的实际类型,只是知道它是你可以迭代的东西(IEnumerable
)。
例如,它可能是一个 returns 无限事物流的生成器(好吧,在这种情况下你知道它不是)。
如果您需要一个具体的集合,您可以使用 .ToList()
将其转换为 List<>
您当然可以迭代多次。
你的IEnumerable
来自这个电话:
Umbraco.ContentAtXPath("root/homepage/events/event")
我不知道具体是如何完成的,因为它是 Umbraco 业务,但 IEnuemerable
本身允许 "lazy" 评估。这意味着例如如果您在没有缓冲的情况下从 SQL 数据库中读取,则每次迭代时它都会读取。
根据数据,它可以 return 相同的结果或新的结果(如果数据已更改)。因此,您在 IEnumerable
中得到的内容完全取决于实现细节,因此,如果您重申,您不知道幕后发生了什么(从没什么特别的到新的数据库查询)。
要在 IEnumerable
的来源未知时防止此行为,您可以在查询结束时执行 ToList()
:
Umbraco.ContentAtXPath("root/homepage/events/event")
.Select(x => new Event(x))
.ToList();
将发生的事情是您遍历一次集合并将所有元素添加到列表中。除非您自己执行此操作,否则此列表不会更改。
我正在建立一个 Umbraco 8 网站并且 运行 遇到了一些奇怪的行为。该项目正在使用.NET 4.7.2。
基本上,我有一个 Event
类型的 IENumerable,这是一个简单的内容列表,我想将其呈现到列表中。但是,每当我对列表(包含项目)执行任何操作时,列表都会立即清空。这包括简单地分配给不同的变量,检查 null 等。
我不认为这是 Umbraco 8 的问题,但为了清楚起见,我目前正在 运行 通过 Surface Controller 并通过在我的视图中调用以下命令来渲染它:
@Html.Action("RenderUpcoming", "Events")
这是控制器:
using Index.Models.Events;
using Index.Models.PublishedContent;
using Papermoon.Umbraco.Kupo.Core.Services.Interfaces;
using System;
using System.Linq;
using System.Web.Mvc;
using Umbraco.Web.Mvc;
namespace Index.Web.Controllers.Surface
{
public class EventsController : SurfaceController
{
private readonly KupoGeneralSettings _kupoGeneralSettings;
public EventsController(IKupoSettingsService kupoSettingsService)
{
_kupoGeneralSettings = kupoSettingsService.GetSettings<KupoGeneralSettings>("kupoGeneralSettings");
}
public ActionResult RenderUpcoming()
{
UpcomingEventsModel model = new UpcomingEventsModel();
model.Title = "Upcoming Events";
model.Events = Umbraco.ContentAtXPath("root/homepage/events/event").Select(x => new Event(x));
model.Events = model.Events.Where(x => x.StartDate > DateTime.Now).OrderBy(x => x.StartDate).Take(3);
model.TotalEvents = model.Events.Count();
model.EventListingLink = _kupoGeneralSettings.EventListingLink;
return PartialView("~/Views/Partials/Events/UpcomingEvents.cshtml", model);
}
}
}
所以在这里,当我调用 model.Events = model.Events.Where(x => x.StartDate > DateTime.Now).OrderBy(x => x.StartDate).Take(3);
- 我有结果,然后当我调用 model.TotalEvents = model.Events.Count();
时,列表 (model.Events) 是空的。
当我分配给另一个变量时,当我调用 model.Events.Any()
时,甚至当我执行 Model.Events != null
.
展示这件事可能比说出来更容易,所以请看随附的 gif 动图:https://i.imgur.com/rE3VAqe.gif
谢谢,
本
当然 – 你不知道对象的实际类型,只是知道它是你可以迭代的东西(IEnumerable
)。
例如,它可能是一个 returns 无限事物流的生成器(好吧,在这种情况下你知道它不是)。
如果您需要一个具体的集合,您可以使用 .ToList()
将其转换为 List<>
您当然可以迭代多次。
你的IEnumerable
来自这个电话:
Umbraco.ContentAtXPath("root/homepage/events/event")
我不知道具体是如何完成的,因为它是 Umbraco 业务,但 IEnuemerable
本身允许 "lazy" 评估。这意味着例如如果您在没有缓冲的情况下从 SQL 数据库中读取,则每次迭代时它都会读取。
根据数据,它可以 return 相同的结果或新的结果(如果数据已更改)。因此,您在 IEnumerable
中得到的内容完全取决于实现细节,因此,如果您重申,您不知道幕后发生了什么(从没什么特别的到新的数据库查询)。
要在 IEnumerable
的来源未知时防止此行为,您可以在查询结束时执行 ToList()
:
Umbraco.ContentAtXPath("root/homepage/events/event")
.Select(x => new Event(x))
.ToList();
将发生的事情是您遍历一次集合并将所有元素添加到列表中。除非您自己执行此操作,否则此列表不会更改。