Introduction to the Entity Framework 6 using MVC5 (eight)--Update related data for ASP.net MVC application

Source: Internet
Author: User
Tags error handling
read related data for ASP.net MVC application

This is the Microsoft Official tutorial Getting started with Entity Framework 6 Code The 5 Series translation, this is eighth: Update related data for ASP.net MVC application

Original: Updating Related Data with the Entity Framework in a asp.net MVC application

You have successfully displayed the relevant data in the previous tutorial. In this tutorial you will learn how to update related data. For most relationships, you can update from a primary key or from a navigation property. For Many-to-many relationships, the Entity Framework does not directly expose join tables, so you can add and remove entities from the corresponding navigation properties.

Create and edit pages for a course customization

When creating a new course entity, he must have a relationship with an existing system. For this reason, the Controller method created by scaffolding code and the new and edited view Seed beans contain a drop-down list for selecting the system. The Drop-down list is used to set the Course.departmentid foreign key property, which is necessary for the Entity Framework to load Department entities by department navigation properties. You'll use scaffolding code, but you'll need to make some minor changes to add error handling and sort the list content.

In Coursecontroller.cs, delete the previous create and edit methods and add the following code:

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"); The catch (retrylimitexceededexception/* dex */) {//log The error uncomment dex variable name and a
        DD a line here to write a log.) Modelstate.addmodelerror ("", "unable to save changes.)
    Try again, and if the problem persists, and the your system administrator. "); Populatedepartmentsdropdownlist (course.
    DepartmentID);
Return View (course); Public ActionResult Edit (int? id) {if (id = = NULL) {return new Httpstatuscoderesult httpstatuscode.ba
    Drequest); } 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 this to write a log. Modelstate.addmodelerror ("", "unable to save changes.)
    Try again, and if the problem persists, and the your system administrator. ");}
    Populatedepartmentsdropdownlist (Coursetoupdate.departmentid);
Return View (coursetoupdate); } Private void Populatedepartmentsdropdownlist (object selecteddepartment = null) {var departmentsquery = from D in Db.
    Departments by D.name Select D;
Viewbag.departmentid = new SelectList (departmentsquery, "DepartmentID", "Name", selecteddepartment);  }

Add the following references at the beginning of the file:

Using System.Data.Entity.Infrastructure;

The Populatedepartmentsdropdownlist method gets all the series tables and sorts them by name to create a drop-down list. and passed through the ViewBag property to the view. The method receives an optional parameter selecteddepartment, which allows the calling code to specify the selected item when rendering the Drop-down list. The view passes the DepartmentID name to the Drop-down List helper, and the helper knows that the DepartmentID name should be used to find the Drop-down list of objects in ViewBag.

The HttpGet create method calls the Populatedepartmentsdropdownlist method, but does not set the selected item because, for a new course, the system to which it belongs has not been determined.

Public ActionResult Create ()
{
    populatedepartmentsdropdownlist ();
    return View ();
}

The Httpgetedit method sets the selected item, based on the ID of the department that has been assigned to the course being edited:

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

The HttpPost method for Create and edit also includes the code to set the selected item again when the page is displayed again when an error occurs:

   catch (retrylimitexceededexception/* dex *
   /) {
      //log the error uncomment Dex variable name and add a To write a log.)
      Modelstate.addmodelerror ("", "unable to save changes.) Try again, and if the problem persists, and the your system administrator. ")
   ;
   Populatedepartmentsdropdownlist (course. DepartmentID);
   Return View (course);

This code ensures that the selected system remains selected when the page displays the error message again.

The

Course view has built a drop-down list using scaffolding based on the system field. But you do not want to use the ID to be the title, so in views\course\create.cshtml you make the following highlights changes:

@model ContosoUniversity.Models.Course @{viewbag.title = "Create";}  

Then make the same changes in the edit view.

Typically scaffolding does not use primary keys to generate fields because primary key values are generated by the database, cannot be changed, and are not meaningful to the user. For the course Entity Scaffolding Code contains a text box for CourseID because the Databasegeneratedoption.none attribute means that the user should be able to enter the primary key value. But it doesn't make sense because the number is meaningful only if you want it to appear in some particular view. So you need to add it manually.

In edit view, add the course Number field before the Title field.

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

There is already a hidden field (Html.hiddenfor Helper) for the course number in the edit view. It is not necessary to add a html.labelfor helper to the hidden field. Because it does not cause the course number to be included in the data to be sent when the user clicks on the save.

In the delete and Details view, change the title of the system name from "name" to "Department" and add a course Number field before the Title field.

<dt>
    Department
</dt>

<dd>
    @Html. Displayfor (model => model. Department.name)
</dd>

<dt>
    @Html. Displaynamefor (model => model. CourseID)
</dt>

<dd>
    @Html. Displayfor (model => model. CourseID)
</dd>

Run the application, open the course Creation page (show the course index page and click Create New) and enter the data for the new course:

Click Create, and the course Index page displays the course you just created. At the same time, the name of the index page is from the navigation property, indicating that the relationship has been correctly established.

Click to edit the hyperlink to run the edit page.

add an edit page to the instructor

When you edit an instructor's record, you want to be able to update the instructor's office assignments. There is one to zero or one relationship between the instructor entity and the Office assignment entity. This means that you must handle the following situations: If the user clears the office assignment and the instructor originally owned one, you must remove and delete the OfficeAssignment entity. If the user enters an office and the original instructor is not assigned, you must create a new officeassignment entity. If the user changes the office assignment value, you must change the officeassignment entity that already exists.

Open InstructorController.cs and check the HttpGet method for edit:

{
    if (id = = null)
    {return
        new Httpstatuscoderesult (httpstatuscode.badrequest);
    }
    Instructor Instructor = db. Instructors.find (ID);
    if (instructor = = null)
    {return
        httpnotfound ();
    }
    Viewbag.id = new SelectList (db. Officeassignments, "Instructorid", "Location", instructor.id);
    Return View (instructor);
}

Scaffolding generates code that is not what you want. It sets a drop-down list, but you need a text half box. Replace the original by using the following code:

Public ActionResult Edit (int? id)
{
    if (id = = null)
    {return
        new Httpstatuscoderesult ( httpstatuscode.badrequest);
    }
    Instructor Instructor = db. Instructors
        . Include (i => i.officeassignment)
        . Where (i => i.id = = ID)
        . Single ();
    if (instructor = = null)
    {return
        httpnotfound ();
    }
    Return View (instructor);
}

This code deletes the ViewBag statement and adds preload for the associated officeassignment entity. You can't use preload on the Find method. So here you use the where and single methods to select the instructor.

The following code replaces the HttpPost edit method. Used to process Office Assignment updates:

[HttpPost, ActionName ("Edit")] [Validateantiforgerytoken] public actionresult editpost (int? id) {if (id = null) {return new httpstatus
    Coderesult (httpstatuscode.badrequest); var instructortoupdate = db. Instructors. Include (i => i.officeassignment). Where (i => i.id = = ID).

    Single (); if (TryUpdateModel (Instructortoupdate, "", new string[] {"LastName", "Firstmidname", "HireDate", "officeassignment
          "})" {try {if (String.isnullorwhitespace (instructorToUpdate.OfficeAssignment.Location))
          {instructortoupdate.officeassignment = null; } db.

          SaveChanges ();
       Return redirecttoaction ("Index"); catch (retrylimitexceededexception/* dex */) {//log The error uncomment dex variable name and a
         DD A line is here to write a log. Modelstate.addmodelerror ("", "unable to save changes.) Try again, and if the problem persists, check your system administrator. ");}}
Return View (instructortoupdate); }

Then add the following references:

Using System.Data.Entity.Infrastructure;

This code does the following: Change the method name to Editpost because the signature is now the same as the HttpGet method. (Still using the edit URL specified by the ActionName attribute) to obtain the OfficeAssignment navigation properties of the current instructor entity from the database using deferred loading. As you did in the HttpGet edit method. To update the retrieved instructor entity from the model binder, use the TryUpdateModel overload to allow you to specify a whitelist of the attribute values you want to include, which prevents excessive publishing of attacks, as described in section II of the tutorial.

   if (TryUpdateModel (Instructortoupdate, "",
      new string[] {"LastName", "Firstmidname", "HireDate", " OfficeAssignment "}))
If the office location is empty, the Instructor.officeassignment property is set to NULL, and the related rows in the OfficeAssignment table are deleted.
if (String.isnullorwhitespace (instructorToUpdate.OfficeAssignment.Location))
{
    Instructortoupdate.officeassignment = null;
}
Saves the changes to the database.

In edit view, after the DIV element in the Hire date field, add a new field to edit the office address:

<div class= "Form-group" >
    @Html. labelfor (model => model. Officeassignment.location, new {@class = "Control-label col-md-2"})
    <div class= "col-md-10" >
        @ Html.editorfor (model => model. officeassignment.location)
        @Html. Validationmessagefor (model => model. officeassignment.location)
    </div>
</div>

Run the page (select the Teacher's tab, then click on the editing instructor), change the office location, and save.

Add a course assignment for a teacher edit page

A teacher can teach any number of courses. You will now add the change to the course assignment by using a set of check boxes, as follows:

The relationship between course and instructor entities is many-to-many, which means that you do not need to directly access foreign key properties in the connection table. Instead, you can add and remove entities from the Istructor.courses navigation properties.

The UI enables you to change the use of a set of check boxes to indicate which courses are already assigned to teachers. Each course in the database uses a check box to display what is already assigned to the teacher. Users can change course assignments by selecting or clearing check boxes. If the number of courses is too large, you may want to use different methods of displaying data in the view, but you will use the same method to manipulate navigation properties to create or delete relationships.

To provide a list of check boxes for the view, you use the ViewModel class to create the AssignedCourseData.cs in the ViewModels folder and replace the auto-generated by using the following code:

Namespace Contosouniversity.viewmodels
{public
    class Assignedcoursedata
    {public
        int CourseID {get; Set Public
        string Title {get; set;}
        public bool assigned {get; set;}}}

In InstructorController.cs, replace the HttpGet edit method with the following code, highlighting the changes you made:

Public ActionResult Edit (int? id) {if (id = = NULL) {return new Httpstatuscoderesult Httpstatuscode.badre
    Quest); } Instructor Instructor = db. Instructors. Include (i => i.officeassignment). Include (i => i.courses). Where (i => i.id = = ID).
    Single ();
    Populateassignedcoursedata (instructor);
    if (instructor = null) {return httpnotfound ();
Return View (instructor); private void Populateassignedcoursedata (instructor instructor) {var allcourses = db.
    Courses; var instructorcourses = new Hashset<int> (instructor.
    Courses.select (c => c.courseid));
    var ViewModel = new list<assignedcoursedata> (); foreach (var course in allcourses) {Viewmodel.add (new Assignedcoursedata {CourseID = Cou Rse. CourseID, Title = course. Title, assigned = Instructorcourses.contains (course.
    CourseID)}); } viewbag.courses = VieWmodel; }

The code preload the courses navigation property and invokes a new Populateassignedcoursedata method that uses the Assignedcoursedata view model class to provide information for the checkbox array.

The code in the Populateassignedcourse method loads the list by reading all the course entities and using the Model view class. In each course, the code checks to see if the course exists in the instructor's courses navigation properties. In order to create an efficient check whether a course is assigned to a teacher, the assigned course is put into a HashSet collection. The Assigned property is true when the course is assigned. The view uses this property to determine which check boxes should be displayed as selected. Finally, the list is passed to the view as the ViewBag property.

Next, add the code that users should execute when they click Save. Call a new method to update the courses navigation properties of the instructor entity, replacing the Editpost method with the following code, highlighting the changes you made:

[HttpPost]
        [Validateantiforgerytoken] public actionresult Edit (int? ID, string[] selectedcourses) {if (id = = NULL) {
    return new Httpstatuscoderesult (httpstatuscode.badrequest); var instructortoupdate = db. Instructors. Include (i => i.officeassignment). Include (i => i.courses). Where (i => i.id = = ID).

    Single (); if (TryUpdateModel (Instructortoupdate, "", new string[] {"LastName", "Firstmidname", "HireDate", "officeassignment 
            "})" {try {if (String.isnullorwhitespace (instructorToUpdate.OfficeAssignment.Location))
            {instructortoupdate.officeassignment = null;

            } updateinstructorcourses (Selectedcourses, instructortoupdate); Db.

            SaveChanges ();
        Return redirecttoaction ("Index");  catch (retrylimitexceededexception/* dex */) {//log The error uncomment dex variable name and Add a line this to write a log. Modelstate.addmodelerror ("", "unable to save changes.)
    Try again, and if the problem persists, and the your system administrator. ");}
    Populateassignedcoursedata (instructortoupdate);
Return View (instructortoupdate); } private void Updateinstructorcourses (string[] selectedcourses, instructor instructortoupdate) {if (selectedcourses =
      = null) {instructortoupdate.courses = new list<course> ();
   Return
   var selectedcourseshs = new hashset<string> (selectedcourses);
   var instructorcourses = new Hashset<int> (InstructorToUpdate.Courses.Select (c => c.courseid)); foreach (var course in db.) Courses) {if (Selectedcourseshs.contains) (course. Courseid.tostring ())) {if (!instructorcourses.contains) (course.
         CourseID)) {INSTRUCTORTOUPDATE.COURSES.ADD (course); } else {if (Instructorcourses.contains courSe.
         CourseID)) {instructorToUpdate.Courses.Remove (course); }
      }
   }
}

Because the method signature is now different from the HttpGet edit method, the name of the method is returned from Editpost to edit.

Because the view does not have a collection of course entities, the model binder cannot automatically update the courses navigation properties. Unlike using model bindings to update course navigation properties, you will update them in the Updateinstructorcourses method. Therefore, you need to exclude the course property from the model binder. This doesn't need to change any code, because the whitelist overload list you are using does not contain courses.

If no check box is selected, the code in Updateinstructorcourses uses an empty collection to initialize the courses navigation properties.

if (selectedcourses = = null)
{
    instructortoupdate.courses = new list<course> ();
    return;
}

By looping through all the courses in the database, the code examines which courses are assigned to teachers to decide whether they should be selected in the view. For efficient lookups, they are stored in the HashSet object.

If the check box for a course is selected but the course is not in the Instructor.courses navigation properties, the course is added to the collection of navigation properties.

if (Selectedcourseshs.contains (course
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.