C#IEnumerable访问后清空

时间:2019-04-29 13:30:28

标签: c# .net umbraco umbraco8

我正在建立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时,也会发生这种情况。

显示此内容可能比说起来容易,因此请查看发生的情况的相关图片:https://i.imgur.com/rE3VAqe.gif

谢谢

2 个答案:

答案 0 :(得分:2)

您的IEnumerable来自此电话:

Umbraco.ContentAtXPath("root/homepage/events/event")

由于它是Umbraco公司的业务,我不知道该如何做,但是IEnuemerable本身允许“惰性”评估。这意味着例如如果您是从SQL数据库读取而不进行缓冲,则每次迭代时都会读取。

根据数据,它可以返回相同的结果或新的结果(如果数据已更改)。因此,您在IEnumerable中获得的收益完全取决于实现细节,因此,如果您重申,您将不知道幕后发生了什么(从没什么特别的到新的数据库查询)。

要防止在IEnumerable的来源未知时发生此现象,可以在查询结束时执行ToList()

Umbraco.ContentAtXPath("root/homepage/events/event")
   .Select(x => new Event(x))
   .ToList();

将发生的情况是,您遍历集合一次并将所有元素添加到列表中。除非您自己进行操作,否则此列表不会更改。

答案 1 :(得分:1)

确定–您不知道对象的实际类型,只是可以对其进行迭代(IEnumerable)。

例如,它可能是一个生成器,它返回无限的事物流(嗯,在这种情况下,您知道不是这样)。

如果您需要具体的集合,则可以使用.ToList()将其转换为List<>,当然可以多次迭代。