更新一对多独立关联关系已断开连接的方案

时间:2015-01-07 16:41:51

标签: c# asp.net-mvc-4 entity-framework-6 one-to-many

我正在使用EF 6,MVC 4(或5)并尝试更新我的2个实体之间的关系,这些实体之间已建立了独立关联

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;}
}

在我的保存/编辑操作方法中,我似乎无法获得更新的关系

[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>

问题是,当调用savechanges时,我得到并发问题或者ActivityGroup根本不更新。 我知道我可以在课堂上添加一个FK,但我真的不愿意。肯定有办法让这个工作? EF根本不处理这个吗?

1 个答案:

答案 0 :(得分:1)

最佳方式是添加外键属性,无论您是否真的愿意。这里的问题是你发布了整个相关模型,或者更正确发布整个相关模型,因为发布的唯一属性是它的id。这导致两种同样令人讨厌的可能性:

  1. 如果您没有手动向实体框架表明修改相关项目,它将尝试添加它。但是,由于发布的id已经属于数据库中的现有项目,因此将引发异常。

  2. 如果你表明它是一个更新,那么除了id之外的所有属性都将更新为null,因为没有在类上设置,基本上是对数据进行borking。 / p>

  3. 通过仅发布外键,您将不会遇到任何问题。如果您真的坚持不添加外键属性,那么您唯一的选择是在视图模型上拥有一个属性来保存外键发布的值,然后使用该属性在后期操作中查看数据库中的新对象。换句话说:

    @Html.DropDownListFor(m => m.ActivityGroupId, ...)
    

    然后在你的行动中:

    var activityGroup = db.ActivityGroups.Find(model.ActivityGroupId);
    if (activityGroup != null)
    {
        model.Activity.ActivityGroup = activityGroup;
    }