0

I have two tables in my DB: Student(many) and Department (one) and a one to many relationship. I want to show a list with DepartmentName for each StudentName, but I get this error: System.NullReferenceException: Object reference not set to an instance of an object.

This is my controller code (the code works fine for one to one relations):

        public ActionResult Index()
    {

        List<Students> studlist = db.Students.ToList();
        StudentViewModel studlistVM = new StudentViewModel();

        List<StudentViewModel> studlistVMList = studlist.Select(x => new StudentViewModel
        {
            StudID = x.StudID,
            StudName = x.StudName,
            DeptName = x.deptobj.DeptName


        }).ToList();


        return View(studlistVMList);
    }
  • What line is the error on? – mcalex Nov 12 '18 at 07:50
  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Fabio Nov 12 '18 at 08:33
  • Harald's answer should get you there. My guess would be that your "deptobj" on Students is not set as virtual so it doesn't lazy load. You should not rely on lazy loading in any case, so Harald covers off how to better select related data from the DbContext rather than a ToList() on one entity type then trying to populate a view model from it's related data via either eager or lazy loading.. – Steve Py Nov 12 '18 at 10:49

1 Answers1

1

Alas you forgot to show us your classes. If you followed the entity framework code first conventions, you'll have classes similar to the following:

class Department
{
    public int Id {get; set;}
    ...

    // Every department has zero or more Students (one-to-many)
    public virtual ICollection<Student> Students {get; set;}
}

class Student
{
    public int Id {get; set;}
    ...

    // every Student belongs to exactly one department, using foreign key
    public int DepartmentId {get; set;}
    public virtual Department Department {get; set;}
}

And your DbContext

class UniversityContext : DbContext
{
     public DbSet<Department> Departments {get; set;}
     public DbSet<Student> Students {get; set;}
}

This is all that Entity Framework needs to know to identify your tables, the columns in the tables and the one-to-many relation between the tables

Note: in entity framework the columns in a table are represented by non-virtual properties. The virtual properties represent the relations between the tables

The virtual properties make your life much easier, because you don't have to do (group)joins anymore. Just use the virtual collections, entity framework will translate this into the proper joins.

I want to show a list with DepartmentName for each StudentName,

var result = universityDbContext.Students
    .Where(student => ...)                 // only if you don't want all Students
    .Select(student => new
    {
        // select only the properties you plan to use
        Id = student.Id,
        StudentName = student.Name,

        DepartmentName = student.Department.Name,
    });

Because you used student.Department, entity framework knows that a SQL join is needed.

If you want a flat SQL join, start with the 'many' side, and use the virtual property to the 'one' side. If you want a grouped join, start with the 'one' side and use the virtual ICollection to the 'many' side.

You wanted a flat join, but if you wanted Departments with their Students you would have done something like:

var result = myDbContext.Departments
    .Where(department => ...)             // if you don't want all departments
    .Select(department => new
    {
        // select only the properties you plan to use
        Id = department.Id,
        Name = department.Name,

        StudentsWithHighGrades = department.Students
            .Where(student => student.Grade >= ...)
            .Select(student => new
            {
                Id = student.Id,
                Name = student.Name,
                Grade = student.Grade,
                ...
            })
            .ToList();
    });
Harald Coppoolse
  • 24,051
  • 6
  • 48
  • 92
  • Thank you, Harard! I've used this code in my controller: public ActionResult Index() { UniversityContext db = new UniversityContext(); var results = db.Departments .Select(department => new { ID = department.Id, Name = department.DepName, }).ToList(); return View(results); } Using a viewmodel, but I get this error: – Mihai Joimir Nov 16 '18 at 10:29