C # IEnumerable опустошается после доступа - PullRequest
0 голосов
/ 29 апреля 2019

Я нахожусь в процессе настройки веб-сайта Umbraco 8 и столкнулся с каким-то странным поведением.В проекте используется .NET 4.7.2.

По сути, у меня есть IENumerable типа Event, простой список содержимого, которое я хотел бы отобразить в списке.Однако всякий раз, когда я что-то делаю со списком (в котором есть элементы), список немедленно очищается.Это включает в себя просто присвоение другой переменной, проверку на нулевое значение и т. Д.

Я не верю, что это проблема 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

Спасибо,

Бен

Ответы [ 2 ]

2 голосов
/ 29 апреля 2019

Ваш 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 голос
/ 29 апреля 2019

Конечно - вы не знаете фактический тип объекта, кроме того, что вы можете итерировать по нему (IEnumerable).

Это может быть генератор, который возвращает бесконечный поток вещейНапример, (ну, в данном случае вы знаете, что это не так).

Если вам нужна конкретная коллекция, вы можете использовать .ToList() для приведения ее к List<>, которую вы, безусловно, можете повторять несколько раз.

...