添加到集合时修改了集合

本文关键字:集合 修改 添加 | 更新日期: 2023-09-27 18:27:23

尝试添加到集合时出现"Collection was modified"异常

public void UpdateLinks(EventViewModel form)
{
    var selectedIds = form.Links.Select(r => r.ResourceTypeID).ToList();
    var assignedIds = form.Event.Links.Select(r => r.ResourceTypeID).ToList();
    foreach (var resource in form.Links)
    {
        resource.EventID = form.Event.ID;
        if (!assignedIds.Contains(resource.ResourceTypeID))
            form.Event.Links.Add(resource);
    }
    foreach (var resource in form.Event.Links.ToList())
    {
        if (!selectedIds.Contains(resource.ResourceTypeID))
            form.Event.Links.Remove(resource);
    }
}

问题特别在于"Add"方法。如果我把那个部分注释掉,就不会抛出任何异常。需要注意的是,我已经尝试过将foreach重写为for循环,并将"ToList()"添加到form.Links中。在所有情况下都会抛出相同的异常。我在网站的其他部分使用这个确切的模式,没有问题,这就是为什么这是如此令人沮丧。这也适用于"创建"。该问题只影响"编辑"操作。

其他相关代码:

[HttpPost]
public ActionResult Edit(EventViewModel form, HttpPostedFileBase[] eventFiles)
{
    if (ModelState.IsValid)
    {
        eventsService.UpdateEvent(form.Event);
        eventsService.UpdateManufacturerTags(form);
        eventsService.UpdateFiles(form, eventFiles);
        eventsService.UpdateLinks(form);
        eventsService.Save();
        return RedirectToAction("Details", new { id = form.Event.ID });
    }
    return View(form);
}
public class EventViewModel : ContentLeftViewModel
{
    public Event Event { get; set; }
    public string[] SelectedManufacturers { get; set; }
    public MultiSelectList Manufacturers { get; set; }
    public IList<EventResource> Files { get; set; }
    public IList<EventResource> Links { get; set; }
    public EventViewModel()
    {
        SelectedManufacturers = new string[0];
        Files = new List<EventResource>();
        Links = new List<EventResource>();
    }
}
public class Event
{
    [Key]
    public int ID { get; set; }
    [Required]
    public string Title { get; set; }
    [Required]
    [DisplayName("Start Time")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:M/d/yyyy h:mm tt}")]
    public DateTime? StartTime { get; set; }
    [Required]
    [DisplayName("End Time")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:M/d/yyyy h:mm tt}")]
    public DateTime? EndTime { get; set; }
    public string Venue { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    [AllowHtml]
    [DataType(DataType.MultilineText)]
    public string Description { get; set; }
    [DisplayName("Registration Link")]
    public string RegistrationUrl { get; set; }
    public virtual IList<Manufacturer> Manufacturers { get; set; }
    public virtual IList<EventResource> Files { get; set; }
    public virtual IList<EventResource> Links { get; set; }
    //public IEnumerable<EventResource> Resources
    //{
    //    get { return Files.Concat(Links); }
    //}
    public string StartDate
    {
        get { return StartTime.Value.ToShortDateString(); }
    }
    public string StartTimeOnly
    {
        get { return StartTime.Value.ToShortTimeString(); }
    }
    public string EndDate
    {
        get { return EndTime.Value.ToShortDateString(); }
    }
    public string EndTimeOnly
    {
        get { return EndTime.Value.ToShortTimeString(); }
    }
    public Event()
    {
        Manufacturers = new List<Manufacturer>();
        Files = new List<EventResource>();
        Links = new List<EventResource>();
    }
}
public class EventResource
{
    [Key, Column(Order = 0)]
    public int EventID { get; set; }
    [Key, Column(Order = 1)]
    public int ResourceTypeID { get; set; }
    [Key, Column(Order = 2)]
    public string Path { get; set; }
    public virtual Event Event { get; set; }
    public virtual ResourceType Type { get; set; }
}

更新

更多信息:正在添加到集合中。。。即使在循环之外也会抛出相同的错误。这能给任何人一个想法吗?

添加到集合时修改了集合

试试这个:

var lsEvents = form.Event.Links.ToList();
foreach (var resource in form.Links)
{
    resource.EventID = form.Event.ID;
    if (!assignedIds.Contains(resource.ResourceTypeID))
        lsEvents.Add(resource);
}
foreach (var resource in form.Event.Links)
{
    if (!selectedIds.Contains(resource.ResourceTypeID))
        lsEvents.Remove(resource);
}

并根据需要使用CCD_ 1。这将解决您的问题。

您可以在添加条目之前使用LINQ过滤掉条目。

public void UpdateLinks(EventViewModel form)
{
    var selectedIds = form.Links.Select(r => r.ResourceTypeID).ToArray();
    var assignedIds = form.Event.Links.Select(r => r.ResourceTypeID).ToArray();
    foreach (var resource in form.Links
        .Where(r=> !assignedIds.Contain(r.ResourceTypeID)).ToArray())
    {
        resource.EventID = form.Event.ID;
        form.Event.Links.Add(resource);
    }
    foreach (var resource in form.Event.Links
        .Where(r=> !selectedIds.Contain(r.ResourceTypeID)).ToArray())
    {
        form.Event.Links.Remove(resource);
    }
}

在这两种方法中,我们都是在枚举和添加之前过滤资源。不能同时枚举和添加。

您不能修改正在枚举的集合(例如,对于每个集合)。

您需要循环一次以获得要添加和/或删除的项目,然后在第一个循环之外的第二个循环中添加或删除所有项目。

例如:

Dim coll = New List(of String)({"1", "2", "3", "4", "6"})
dim coll2 = New List(of String)({"5", "8", "9", "2"})
Dim removeItems as new list(of String)()
For Each item in coll
 For Each item2 in coll2
  If item2 = item
    removeItems.Add(item)
  end if
 Next item2
Next item
' remove the items gathered
For each itemToRemove in removeItems
 coll.Remove(itemToRemove)
Next itemToRemove

可以用更好的方法来做,但这说明了错误的要点。您无法更改正在循环的集合。

不确定是什么原因解决了这个问题,但在升级到Visual Studio 2013学习版(从2010 Professional开始)并安装了ASP.Net 4.5/IIS8之后,即使这个应用程序继续以ASP.Net 4.0为目标,我也不再遇到这个问题,原始帖子中使用的代码也能正常工作。

也许这是由ASP.Net框架的某个版本或IIS的旧版本引起的?