Update navigation properties in ASP.NET MVC

两盒软妹~` 提交于 2019-12-25 04:26:33

问题


You can see my database diagram on my previous post: MVC EF - Update navigation property

I want to delete and insert categories for one post. I get the error Collection was modified; enumeration operation may not execute. at the row

foreach (PostMapping pm in current_list_category)

This is my function:

//
// POST: /BlogPost/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Post post, int[] selectedCategories)
{
   if (ModelState.IsValid)
   {
     List<PostMapping> current_list_category = db.PostMappings.Where(p => p.PostID == post.ID).ToList();
     post.PostMappings = current_list_category;      
     foreach (PostMapping pm in current_list_category)
     {
        int categoryId = pm.CategoryID.Value;
        if (selectedCategories != null)
        {
           if (selectedCategories.Contains(categoryId))
           {
              selectedCategories = selectedCategories.Where(val => val != categoryId).ToArray();
           }
           else
           {
              post.PostMappings.Remove(pm);
              Category category = db.Categories.Where(c => c.ID == categoryId).SingleOrDefault();
              category.PostMappings.Remove(pm);
           }
        }                  
     }
     foreach (var id in selectedCategories)
     {
        Category category = db.Categories.Where(c => c.ID == id).SingleOrDefault();
        PostMapping postMap = new PostMapping();
        postMap.Category = category;
        postMap.Post = post;
        postMap.ID = Guid.NewGuid();
        post.PostMappings.Add(postMap);
        category.PostMappings.Add(postMap);
     }
     db.Entry(post).State = EntityState.Modified;       
     db.SaveChanges();
     return RedirectToAction("Index");
   }
   return View(post);
}

Is there another approach?


I don't get anymore the error but now I have another problem.

Before updating I have this in database:

PostID CategoryID
1 1
1 2
1 3

, but after I update(I want to remove categories with ids 1,2,3 and add category with id 4)

PostID CategoryID
1 NULL
1 NULL
1 NULL
1 4

Why?

I tried another approach but with no succes:

.....
Post post2 = db.Posts.Where(p => p.ID == post.ID).SingleOrDefault();
post2.PostMappings.Remove(pm);
Category category = db.Categories.Where(c => c.ID == categoryId).SingleOrDefault();
category.PostMappings.Remove(pm);
 .....

instead:

....
post.PostMappings.Remove(pm);
Category category = db.Categories.Where(c => c.ID == categoryId).SingleOrDefault();
category.PostMappings.Remove(pm);
.....

But I get the error:AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.


回答1:


You can't change collection while you enumerating it so you need temporary collection and enumerate over it. something like this:

post.PostMappings = current_list_category;

List<PostMapping> temp = new List<PostMapping>();
temp.AddRange(current_list_category);

foreach (PostMapping pm in temp)
        {
            int categoryId = pm.CategoryID.Value;
            if (selectedCategories != null)
            {
                if (selectedCategories.Contains(categoryId))
                {
                    selectedCategories = selectedCategories.Where(val => val != categoryId).ToArray();
                }
                else
                {

                    post.PostMappings.Remove(pm);
                    Category category = db.Categories.Where(c => c.ID == categoryId).SingleOrDefault();
                    category.PostMappings.Remove(pm);
                }
            }

        }

Or even better especially if you have just few items for remove, you can collect removed items in separate list and then enumerate over that list and remove item from source list

Made changes according to post edit:

you also need to mark your removed entries state as EntityState.Deleted




回答2:


Finally I have the answer.

I hope this will help someone.

        //
    // POST: /BlogPost/Edit/5

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(Post post, int[] selectedCategories)
    {

        if (ModelState.IsValid)
        {
            List<PostMapping> current_list_category = db.PostMappings.Where(p => p.PostID == post.ID).ToList();


            List<PostMapping> temp = new List<PostMapping>();
            temp.AddRange(current_list_category);

            if (selectedCategories != null)
            {
                foreach (PostMapping pm in temp)
                {
                    int categoryId = pm.CategoryID.Value;

                    if (selectedCategories.Contains(categoryId))
                    {
                        selectedCategories = selectedCategories.Where(val => val != categoryId).ToArray();
                    }
                    else
                    {

                        post.PostMappings.Remove(pm);

                        db.Entry(pm).State = EntityState.Deleted;

                    }


                }
            }
            else
            {
                foreach (PostMapping pm in temp)
                {
                    int categoryId = pm.CategoryID.Value;

                    post.PostMappings.Remove(pm);

                    db.Entry(pm).State = EntityState.Deleted;
                }
            }


            if (selectedCategories != null)
            {
                foreach (var id in selectedCategories)
                {
                    Category category = db.Categories.Where(c => c.ID == id).SingleOrDefault();
                    PostMapping postMap = new PostMapping();
                    postMap.Category = category;
                    postMap.Post = post;
                    postMap.ID = Guid.NewGuid();

                    post.PostMappings.Add(postMap);

                    category.PostMappings.Add(postMap);
                }
            }

            db.Entry(post).State = EntityState.Modified;

            db.SaveChanges();

            return RedirectToAction("Index");
        }

        return View(post);
    }


来源:https://stackoverflow.com/questions/22477871/update-navigation-properties-in-asp-net-mvc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!