【发布时间】:2013-08-11 04:45:54
【问题描述】:
尝试添加到集合时出现“集合已修改”异常
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);
}
}
问题出在“添加”方法上。如果我将那部分注释掉,则不会引发异常。需要注意的是,我已经尝试将 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; }
}
更新
更多信息:完全添加到集合中......即使在循环之外也会引发相同的错误。这会给任何人一个想法吗?
【问题讨论】:
-
不建议在迭代foreach时修改集合。看看一个简单的for循环是否符合目的
-
如果您在迭代时尝试修改它,每个 .Net 集合都会抛出异常 - 无论它是 for-each 循环还是您获得了迭代器并且正在执行它“通过手”(在 for 或 while 循环中)。尝试使用上面建议的 For-Loop,或者创建一个临时集合,其中包含您以后要删除或添加的数据。
-
在网站的其他部分,我已经成功地对不同类型的实体使用了相同的解决方案。您是对的,但是在其他情况下,添加“ToList()”来创建一个新列表以避免该问题就足够了。我将尝试以下建议。
-
另外,如原帖所述,我已经尝试将 foreach 重写为一个简单的 for 循环。无论哪种方式,我都会遇到相同的异常。
-
还想强调代码原样在 Create 上完美运行。以这种方式删除项目也适用于编辑。问题出在在 Edit 上执行时此方法的 add 部分。还有其他想法吗?
标签: c# asp.net-mvc entity-framework collections