HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Eager load additional data about some instructors

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
eagerinstructorsaboutsomeloaddataadditional

Problem

Below is a snippet of code of a little practice project. I am still pretty new to EF and I was wondering if there is a way to write the below statement so that all required data is eager loaded since I have the ID parameter.

public ActionResult Index(int? id)
    {
        var viewModel = new InstructorIndexData
        {
            Instructors = _db.Instructors
                .Include(i => i.OfficeAssignment)
                .Include(i => i.Courses.Select(c => c.Department))
                .OrderBy(i => i.LastName)
        };

        if (id != null)
        {
            ViewBag.InstructorId = id.Value;
            viewModel.Courses = viewModel.Instructors.Single(i => i.InstructorId == id.Value).Courses;
        }

        return View(viewModel);
    }


When this action runs it grabs the instructor data and includes a few other collections because they are required for the initial view of the page. After selecting an instructor the page comes back with the instructor and the course the instructor is assigned to but this requires two calls to the database. Is there a way I can simple add the course to the initial query before it goes out to pull the instructor since that doesnt occur till the return?

Solution

The query to the database wont't be executed by writing this linq statement

var viewModel = new InstructorIndexData
{
    Instructors = _db.Instructors
        .Include(i => i.OfficeAssignment)
        .Include(i => i.Courses.Select(c => c.Department))
        .OrderBy(i => i.LastName)
};


if the InstructorIndexData.Instructors property setter isn't executing any of the following actions

  • enumerating the elements by a for..each loop



  • calling ToArray(), ToDictionary() or ToList() on the IEnumerable



  • calling a linq operator like First(), Any



See: https://msdn.microsoft.com/en-us/data/jj573936.aspx

So, if you call ToList() on the enumerable shown above, only one call to the database will be made.

var viewModel = new InstructorIndexData
 {
     Instructors = _db.Instructors
         .Include(i => i.OfficeAssignment)
         .Include(i => i.Courses.Select(c => c.Department))
         .OrderBy(i => i.LastName)
         .ToList()
 };


The call to

viewModel.Courses = viewModel.Instructors.Single(i => i.InstructorId == id.Value).Courses;


will then operate on the retrieved data and won't need a trip to the database anymore.

Code Snippets

var viewModel = new InstructorIndexData
{
    Instructors = _db.Instructors
        .Include(i => i.OfficeAssignment)
        .Include(i => i.Courses.Select(c => c.Department))
        .OrderBy(i => i.LastName)
};
var viewModel = new InstructorIndexData
 {
     Instructors = _db.Instructors
         .Include(i => i.OfficeAssignment)
         .Include(i => i.Courses.Select(c => c.Department))
         .OrderBy(i => i.LastName)
         .ToList()
 };
viewModel.Courses = viewModel.Instructors.Single(i => i.InstructorId == id.Value).Courses;

Context

StackExchange Code Review Q#82587, answer score: 2

Revisions (0)

No revisions yet.