Reputation: 2296
Below is my code that saves a multi select box, it works fine, but when i try to edit a record i get the error below. Whats the best way to add just the additional selected tags, and to remove any unselected tags when editing?
failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
public class Post
{
public Guid PostId { get; set; }
public string Name { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public int TagId { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class HomeController : Controller
{
public ActionResult Create()
{
var tags = new List<Tag>()
{
new Tag() { TagId = 1, Name = "Planes", Posts = new Collection<Post>() },
new Tag() { TagId = 2, Name = "Cars", Posts = new Collection<Post>() },
new Tag() { TagId = 2, Name = "Boats", Posts = new Collection<Post>() }
};
ViewBag.MultiSelectTags = new MultiSelectList(tags, "TagId", "Name");
return View();
}
[HttpPost]
public ActionResult Create(Post post, int[] tags)
{
foreach (var tag in tags)
{
Tag t = db.ThemeFeatures.Where(t => t.TagId== tag).First();
themedetails.ThemeFeatures.Add(t);
}
context.SaveChanges();
return RedirectToAction("Create");
}
}
Create view
@model MvcApplication1.Models.Post
Create
@using (Html.BeginForm("Create", "Home", FormMethod.Post)) { Name @Html.TextBoxFor(model => model.Name)
<label>Tags For Post</label> @Html.ListBox("Tags", (MultiSelectList)ViewBag.MultiSelectTags) <input type="submit" value="Submit Post"/> }
Upvotes: 0
Views: 1403
Reputation: 12420
What you want to do is make sure the entity you're adding child-entities to is attached to the object context. The easiest way to do this is just get a fresh context object using the POSTed ID from your view.
You won't save anything worrying about getting the difference of what the object has versus what the object should have. The easiest way to handle that is to simply clear the object of its child collection and add everything that came back from the POST.
[HttpPost]
public ActionResult Create(Post post, int[] tags)
{
...
var freshPost = db.Posts.Find(post.ID);
freshPost.Tags.Clear();
foreach (var tag in tags)
{
Tag t = db.ThemeFeatures.Find(tag);
freshPost.Tags.Add(t);
}
context.SaveChanges();
}
Upvotes: 2