简体   繁体   English

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

[英]MVC 4 and lazy loading: “Collection was modified” error when deleting multiple records

In ASP.NET MVC 4 project, I have a model LeagueMember : 在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; }

}

In League model, I have: 在联赛模型中,我有:

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

In the Edit view of League controller, I have a dropdown for LeagueMembers and in its Edit action I am trying to delete existing LeagueMembers and creating new ones: League控制器的Edit视图中,我有一个LeagueMembers的下拉列表,并且在其Edit操作中,我试图删除现有的LeagueMembers并创建新的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);
}

When executed, the line foreach (var leagueMember in leagueMembers) complains on second iteration of forloop: 当执行时, foreach (var leagueMember in leagueMembers)foreach (var leagueMember in leagueMembers)第二次迭代中抱怨:

Collection was modified; 集合已修改; enumeration operation may not execute 枚举操作可能无法执行

Is there a better way to delete bulk records in a one-to-many relationship? 有没有更好的方法来删除一对多关系中的批量记录?

In this case, to Remove All leagueMemberViewModel.League.LeagueMembers perhaps without iterating through the collection? 在这种情况下, 要删除所有leagueMemberViewModel.League.LeagueMembers也许不对集合进行迭代?

Something like, replacing: 诸如此类,替换为:

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

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

with: 与:

 leagueMember.League.LeagueMembers.Remove();

I think your code has some typos. 我认为您的代码有错别字。 For example, it looks like var league = leagueMember.League should be var league = leagueMemberViewModel.League . 例如,它看起来像var league = leagueMember.League应该是var league = leagueMemberViewModel.League Reading between the lines I suspect that leagueMembers is the same as the leagueMembers of the attached league object. 我怀疑字里行间leagueMembers是一样的附着的leagueMembers league对象。 (That you attach by setting EntityState.Modified ). (通过设置EntityState.Modified附加)。

If so, the error is explained by the fact that you loop through a loaded collection and at the same time remove items from it. 如果是这样,则可以通过以下事实来解释该错误:您遍历已加载的集合并同时从中删除项目。 The remedy is simple: 解决方法很简单:

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

which copies the collection to a local array that does not change. 将集合复制到一个不变的本地数组。

As for your second question: no there is no built-in way to do bulk deletes in Entity Framework. 关于第二个问题:在Entity Framework中,没有内置的方法可以进行批量删除。

You cannot modify a collection while iterating through it, the best approach is to use a reverse for loop like this: 您不能在遍历集合时修改集合,最好的方法是使用反向for循环,如下所示:

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

This is a common .NET error, you can get around this by replacing your foreach loop with a for loop: 这是一个常见的.NET错误,您可以通过将foreach循环替换for循环来解决此问题:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM