Reputation: 2197
I am using EF 6, MVC 4 (or 5) and trying to update a relationship between my 2 entities that have an independent association set up thus
public class Activity{
public int ID {get;set;}
public string Description{get;set;}
public ActivityGroup ActivityGroup{get;set;}
}
public class ActivityGroup{
public int ID{get;set;}
public string Description{get;set;}
public ICollection<Activity> Activities{get;set;}
}
in my save/edit action method, I cannot seem to get the relationship to update
[HttpGet]
public ActionResult Edit(int id = 0)
{
EditActivityVM model = new EditActivityVM();
model.Activity = db.Activities.Include(a => a.ActivityGroup).SingleOrDefault(a => a.ID == id);
if (model.Activity == null)
{
return HttpNotFound(string.Format("Activity with ID: {0} not found", id.ToString()));
}
model.ActivityGroups = db.ActivityGroups.ToList();
return View(model);
}
[HttpPost]
public ActionResult Edit(EditActivityVM activity){
if(ModelState.IsValid){
db.Entry(model.Activity).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
public class EditActivityVM{
public ICollection<ActivityGroup> ActivityGroups{get;set;}
public Activity Activity{get;set;}
}
@model EditActivityVM
@Html.HiddenFor(m => m.Activity.ID)
<div class="editor-label">
@Html.LabelFor(model => model.Activity.ActivityGroup.ID)
</div>
<div class="editor-field">
@Html.DropDownListFor(m => m.Activity.ActivityGroup.ID, Model.ActivityGroups.Select(ag => new SelectListItem { Text = ag.Description, Value = ag.ID.ToString() }), "Select Group", null)
@Html.ValidationMessageFor(model => model.Activity.ActivityGroup.ID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Activity.Description)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Activity.Description)
@Html.ValidationMessageFor(model => model.Activity.Description)
</div>
the problem is, that when savechanges is called i either get a concurrency problem or the ActivityGroup simply doesnt update. I know I could add an FK into the class, but really would rather not. surely there must be a way to get this to work? does EF simply not handle this?
Upvotes: 1
Views: 387
Reputation: 239290
The best way is to add an foreign key property, despite whether you really would prefer to or not. The problem here is that you're posting the whole related model, or more correctly not posting the whole related model, because the only property being posted is it's id. This results in two equally nasty possibilities:
If you don't indicate to Entity Framework manually that your modifying the related item, it will attempt to add it. However, since the posted id will already belong to an existing item in the database, an exception will be raised.
If you do indicate that it's an update, then all the properties other than the id will be updated to null, since none are set on the class, essentially borking your data.
By posting only the foreign key, you won't have any problems. If you really insist on not adding a foreign key property, then your only option is have a property on your view model to hold the foreign key posted value and then use that to look the object up fresh from the database in your post action. In other words:
@Html.DropDownListFor(m => m.ActivityGroupId, ...)
Then in your action:
var activityGroup = db.ActivityGroups.Find(model.ActivityGroupId);
if (activityGroup != null)
{
model.Activity.ActivityGroup = activityGroup;
}
Upvotes: 1