MVC 4和延迟加载:删除多个记录时“收集已修改”错误

时间:2013-05-02 15:31:26

标签: c# linq asp.net-mvc-4 entity-framework-5

在ASP.NET MVC 4项目中,我有一个模型LeagueMember

public class LeagueMember
{
    [Key, Column(Order = 0)]
    public int MemberId { get; set; }

    [Key, Column(Order = 1)]
    public int LeagueId { get; set; }

    public bool? IsActive { get; set; }

    public virtual League League { get; set; }

    public virtual Member Member { get; set; }

}

在联盟模式中,我有:

public virtual ICollection<LeagueMember> LeagueMembers { get; set; }

Edit控制器的League视图中,我有LeagueMembers的下拉列表,在其编辑操作中,我尝试删除现有的联盟成员并创建新的联盟成员:

[HttpPost]
public ActionResult Edit(LeagueMembersViewModel leagueMemberViewModel)
{
    if (ModelState.IsValid)
    {
        var league = leagueMemberViewModel.League;
        context.Entry(league).State = EntityState.Modified;

        /* without this line the next foreach statement would complain that 
           League.LeagueMembers is null due to lazy loading..*/
        context.Entry(league).Collection("LeagueMembers").Load();

        var leagueMembers = leagueMemberViewModel.League.LeagueMembers;

        foreach (var leagueMember in leagueMembers)
        {
            context.LeagueMembers.Remove(leagueMember);
        }

        foreach (var memberId in leagueMemberViewModel.SelectedMembers)
        {
            var leagueMember = new LeagueMember { MemberId = memberId, League = league };
            context.LeagueMembers.Add(leagueMember);
        }
        context.SaveChanges();

        return RedirectToAction("Index");
   }

    leagueMemberViewModel.MemberList = new MultiSelectList(context.Members, "Id", "Name", leagueMemberViewModel.SelectedMembers);
    return View(leagueMemberViewModel);
}

执行时,行foreach (var leagueMember in leagueMembers)会在forloop的第二次迭代中抱怨:

  

收藏被修改;枚举操作可能无法执行

有没有更好的方法来删除一对多关系中的批量记录?

在这种情况下,删除所有leagueMemberViewModel.League.LeagueMembers 可能没有遍历集合?

取而代之的是:

context.Entry(league).Collection("LeagueMembers").Load();

var leagueMembers = leagueMemberViewModel.League.LeagueMembers;
foreach (var leagueMember in leagueMembers)
{
    context.LeagueMembers.Remove(leagueMember);
}

使用:

 leagueMember.League.LeagueMembers.Remove();

3 个答案:

答案 0 :(得分:1)

我认为你的代码有一些错别字。例如,var league = leagueMember.League看起来应该是var league = leagueMemberViewModel.League。在行之间阅读我怀疑leagueMembers与附加的league对象的联盟成员相同。 (通过设置EntityState.Modified)附加。

如果是这样,错误的原因在于您遍历已加载的集合并同时从中删除项目。补救措施很简单:

foreach (var leagueMember in leagueMembers.ToArray()) // <= ToArray

将集合复制到不会更改的本地数组。

至于你的第二个问题:没有内置的方法可以在Entity Framework中进行批量删除。

答案 1 :(得分:0)

在迭代过程中无法修改集合,最好的方法是使用反向for循环:

        for (int i = leagueMembers.Count - 1; i >= 0; i--)
        {
            context.LeagueMembers.Remove(leagueMembers[i]);
        }

答案 2 :(得分:-1)

这是一个常见的.NET错误,您可以通过将foreach循环替换为for循环来解决此问题:

for (var i = 0; i < leagueMembers.Count; i++)
{
    context.LeagueMembers.Remove(leagueMembers[i]);
}