Hopefully a very simple question. But I'm using Code First with an MVC app and I have a Category and ServiceType object that have a many to many relationship:
public class Category
{
public Category()
{
ServiceTypes = new HashSet<ServiceType>();
}
public Guid CategoryId { get; set; }
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
public virtual ICollection<ServiceType> ServiceTypes { get; set; }
}
The database has been generated correctly and contains a linking table called CategoryServiceTypes. My issue is I add items to my ServiceTypes collection and call save and although no error takes place, no rows are added to CategoryServiceTypes. When the below code gets to SaveChanges the count on category.ServiceTypes is 1, so something is definitely in the collection:
[HttpPost]
public ActionResult Edit(Category category, Guid[] serviceTypeIds)
{
if (ModelState.IsValid)
{
// Clear existing ServiceTypes
category.ServiceTypes.Clear();
// Add checked ServiceTypes
foreach (Guid serviceType in serviceTypeIds)
{
ServiceType st = db.ServiceTypes.Find(serviceType);
category.ServiceTypes.Add(st);
}
db.Entry(category).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(category);
}
I hope I'm doing something obviously wrong here. Any ideas?
Thanks.
EDIT:
Although the below response is indeed the correct answer I thought I'd add the following final version of the Edit post method:
[HttpPost]
public ActionResult Edit(Category category, Guid[] serviceTypeIds)
{
if (ModelState.IsValid)
{
// Must set to modified or adding child records does not set to modified
db.Entry(category).State = EntityState.Modified;
// Force loading of ServiceTypes collection due to lazy loading
db.Entry(category).Collection(st => st.ServiceTypes).Load();
// Clear existing ServiceTypes
category.ServiceTypes.Clear();
// Set checked ServiceTypes
if (serviceTypeIds != null)
{
foreach (Guid serviceType in serviceTypeIds)
{
ServiceType st = db.ServiceTypes.Find(serviceType);
category.ServiceTypes.Add(st);
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(category);
}
Notice the line that forces the loading of the ServiceTypes collection, this is needed as lazy loading does not include those child items, which means clearing the ServiceTypes collection did nothing.