EF学习笔记:更新关联数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EF学习笔记:更新关联数据相关的知识,希望对你有一定的参考价值。

学习笔记主目录链接:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)

上一篇链接:EF学习笔记(七):读取关联数据

本篇原文链接:Updating Related Data

本篇主要考虑对于有关联的数据进行新增、删除、更新操作;比如Course 、Instructor;

对于Course来说,新增时候必须定义属于哪个Department,所以在新增、更新操作的时候,必须要用户选择Department;

MVC5在选择基础控制器及视图框架的时候,如果选择EF的操作框架,则会自动带一部分基础代码,比如Course的Create\\Edit直接就带上了Department的下拉列表选择框;

但是对于一些错误情况处理不够以及没有做显示排序,原文做了些调整优化;

public ActionResult Create()
{
    PopulateDepartmentsDropDownList();
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "CourseID,Title,Credits,DepartmentID")]Course course)
{
    try
    {
        if (ModelState.IsValid)
        {
            db.Courses.Add(course);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
    }
    catch (RetryLimitExceededException /* dex */)
    {
        //Log the error (uncomment dex variable name and add a line here to write a log.)
        ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
    }
    PopulateDepartmentsDropDownList(course.DepartmentID);
    return View(course);
}

public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Course course = db.Courses.Find(id);
    if (course == null)
    {
        return HttpNotFound();
    }
    PopulateDepartmentsDropDownList(course.DepartmentID);
    return View(course);
}

[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public ActionResult EditPost(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    var courseToUpdate = db.Courses.Find(id);
    if (TryUpdateModel(courseToUpdate, "",
       new string[] { "Title", "Credits", "DepartmentID" }))
    {
        try
        {
            db.SaveChanges();

            return RedirectToAction("Index");
        }
        catch (RetryLimitExceededException /* dex */)
        {
            //Log the error (uncomment dex variable name and add a line here to write a log.
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
        }
    }
    PopulateDepartmentsDropDownList(courseToUpdate.DepartmentID);
    return View(courseToUpdate);
}

private void PopulateDepartmentsDropDownList(object selectedDepartment = null)
{
    var departmentsQuery = from d in db.Departments
                           orderby d.Name
                           select d;
    ViewBag.DepartmentID = new SelectList(departmentsQuery, "DepartmentID", "Name", selectedDepartment);
}

PopulateDepartmentsDropDownList方法给视图传递了一个用Name排序过的Department列表;

并且处理了新建的时候 选中的Department为空的情况;

Create、Edit的Post请求中都对异常情况做了处理,并同时在下拉框还保持原先的选择;

另外,在Create、Edit的视图中,对于Department的标题也需要从DepartmentID改为Department :

<div class="form-group">
     <label class="control-label col-md-2" for="DepartmentID">Department</label>
     @*@html.LabelFor(model => model.DepartmentID, "DepartmentID", htmlAttributes: new { @class = "control-label col-md-2" })*@
     <div class="col-md-10">
          @Html.DropDownList("DepartmentID", null, htmlAttributes: new { @class = "form-control" })
          @Html.ValidationMessageFor(model => model.DepartmentID, "", new { @class = "text-danger" })
     </div>
</div>

另外,对于Create视图,EF默认框架建立的视图会根据主关键字段是不是自动列来采用不同的方式;
如果定义为自动增加列,则不需要用户输入,由数据库自增长;

如果定义为非自动增长列,则需要用户手动,则会提供一个输入框;

但对于Edit视图,EF默认框架建立的视图不会明文显示主关键字段,因为它不知道这个字段到底有没有显示意义,它只用一个隐藏字段来包含主关键字段数据;

所以要手动增加显示主关键字段,但是就算自己手动增加显示主关键字段,也不可以删除那个隐藏字段!

@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.CourseID)

<div class="form-group">
     @Html.LabelFor(model => model.CourseID, new { @class = "control-label col-md-2" })
     <div class="col-md-10">
          @Html.DisplayFor(model => model.CourseID)
     </div>
</div>

<div class="form-group">
     @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
     <div class="col-md-10">
          @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })
          @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
     </div>
</div>

同样,在Delete、Detail视图中,需要加入CourseID的显示:

<dt>
    @Html.DisplayNameFor(model => model.Department.Name)
</dt>
<dd> @Html.DisplayFor(model => model.Department.Name) </dd> <dt> @Html.DisplayNameFor(model => model.CourseID) </dt> <dd> @Html.DisplayFor(model => model.CourseID) </dd> <dt> @Html.DisplayNameFor(model => model.Title) </dt> <dd> @Html.DisplayFor(model => model.Title) </dd>

Course 修改效果:
技术分享技术分享

技术分享

 






以上是关于EF学习笔记:更新关联数据的主要内容,如果未能解决你的问题,请参考以下文章

EF学习笔记:异步处理和存储过程

EF添加关联的提示问题:映射从第 260 行开始的片段时有问题:

EF 使用lambda表达式 更新一对多数据时报错

EF6学习笔记

AngularJS入门学习笔记一

AngularJS的学习笔记