简体   繁体   中英

How to use my view model class and passing data from view model to View on the page?

I need Your help. I create a program in asp.net mvc. I wrote the model class and the ViewModel class

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }
    public int IndexNumber { get; set; }

    public ICollection<Course> Course { get; set; }
}
public class Course
{
    public int CourseId { get; set; }
    public string CoureName { get; set; }
    public int NumberHours { get; set; }
    public bool IsExam { get; set; }

    public ICollection<Student> Student { get; set; }

}
public class ScheduleVM
{
    public string StudentName { get; set; } // Student class
    public int IndexNumber { get; set; }    // Student class
    public string CourseName { get; set; }   // Course class

}

The ScheduleVM class does not exist in the context class, and I want to create a view that only returns the data from the ScheduleVM class. I wrote the Schedule controller manually and have a view. I do not know how to transfer some of this data to the database view using EF and Linq? If anyone has any guide, please send me a link.

Edit:

View from ScheduleVM class:

    @model IEnumerable<StudentApp.Models.ScheduleVM>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.StudentName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.IndexNumber)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.CoureName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.NameInstructor)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DepartmentName)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.StudentName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.IndexNumber)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.CoureName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.NameInstructor)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentName)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
        </td>
    </tr>
}

</table>

The foreach loop does not work, of course, because I do not have a model. I generated the view, but I removed the reference to the context class. Regarding the controller, I do not know how to get the data that I need.

Controller class:

public class ScheduleController : Controller
{

    // GET: Schedule
    public ActionResult Index()
    {
        List<ScheduleVM> ScheduleVMlist = new List<ScheduleVM>();

        return View();
    }
}

I have added data to the student and course table, and now I want to display the selected information, but I do not know how to extract this data from the database ?

public class ModelContext : DbContext
{
    public ModelContext()
        : base("name=ModelContext")
    {}

    public DbSet<Student> Students { get; set; }
    public DbSet<Course> Courses { get; set; }

}

An efficient way is to compose your query across the entities, then use .Select() to populate the relevant view models. You can populate the view models yourself, or leverage a library like Automapper to help with more complex or larger view models. AutoMapper now offers a ProjectTo extension method that plays nice with EF and IQueryable .

So for example if you had a search that looked to list courses with a name starting with a provided criteria:

This assumes that you want the students and course information based on the course name. Students have a Courses collection, but courses do not have a Students collection.

using (var context = new MyContext())
{
  var courseIds = context.Courses
    .Where(c => c.CourseName.StartsWith(searchText))
    .ToList();

  var query = context.Students
    .Where(s => s.Courses.Any(c => courseIds.Contains(c.CourseId)));
}

Now at this point we have an IQueryable which should give us all students that have at least 1 matching course. I split off the course search to retrieve just a list of matching course IDs since these will be easier to match against than embedding that criteria into the following queries. These can be combined, but if you have several different criteria it may be easier to follow by using those to identify IDs for following queries.

Nothing has been run against the database. The next step will be that we want to flatten the result to list the student details with just the matching courses for example. If we searched for "Math" we want to return just the course, or courses for each student that match that pattern. A student may be taking "Math 100" and "Math 200"

using (var context = new MyContext())
{
  var courseIds = context.Courses
    .Where(c => c.CourseName.StartsWith(searchText))
    .ToList();

  var query = context.Students
    .Where(s => s.Courses.Any(c => courseIds.Contains(c.CourseId)));

  var viewModels = query.SelectMany( s => s.Courses.Where(c => courseIds.Contains(c.CourseId))
    .Select(c => new ScheduleVM 
    {
      StudentName = s.StudentName,
      IndexNumber = s.IndexNumber,
      CourseName = c.CourseName
    })).ToList()
}

This can be condensed to a single Linq query, but I kept it separated to make it a bit easier to cover. The first "query" retrieved our students that had matching courses, but at that point that student's course list would be all courses the student is taking. In this example we only want to list matching courses. So from Student we do a SelectMany to get course details, and use a Where condition to only retrieve the courses with the matching IDs. From there we do a .Select against those matching courses. Because we are still within the scope of the SelectMany against the student, we can still access "s" which represents the current student. We "Select" our our view model, providing the relevant columns from Student ("s") and Course ("c"). The ToList at the end is what will actually trigger the SQL to run. EF will compose a query that filters the data, then returns just the 3 columns we need to populate the view model.

Hopefully that gives you some ideas on how to leverage EF to populate the data you want to feed to your view. I would recommend including IDs in your view model, even if you don't display them, because that will be useful for retrieving the relevant student and/or course for any actions you want to take based on this data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM