3

I have created two model classes: Student and Exam.

Student:

class Student
{
    [Key]
    public int StudentId { get; set; }

    [Required, MaxLength(30)]
    public string FirstName { get; set; }

    [Required, MaxLength(50)]
    public string LastName { get; set; }

    [Required]
    public DateTime BirthDate { get; set; }

    public virtual ICollection<Exam> Exams { get; set; } 
}

Exam:

public enum Grade
{
    A, B, C, D, E, F
}
class Exam
{
    [Key]
    public int ExamId { get; set; }

    [Required]
    public Grade Grade { get; set; }

    [ForeignKey("Student"), Required]
    public int StudentId { get; set; }

    public virtual Student Student { get; set; }
}

But it seems Lazy Loading doesn't work, here's example how I retrieve data:

using (var context = new StudentContext())
{
    context.Configuration.LazyLoadingEnabled = true;
    context.Configuration.ProxyCreationEnabled = true;

    var student = context.Students.Single(s => s.LastName == "ABC");

    foreach (var exam in student.Exams)
    {
        Console.WriteLine($"{exam.ExamId}: {exam.Grade}");
    } 
    context.SaveChanges();
}

And I'm getting NullReferenceException when I try to access students.Exams property. What's wrong in my code?

The problem with my code is that Entity Framework Lazy Loading isn't working and I don't know why. It's not about not initializing Exams, because Entity Framework should do it alone when I try to access Exams property.

gunr2171
  • 10,315
  • 25
  • 52
  • 75
monoh_
  • 881
  • 3
  • 11
  • 15
  • @Nasreddine, not really. I have read that EF during Lazy Loading should notice if collection is initialized or not and initialize it. I added initialization in constructor but Lazy Loading still doesn't work. Now when I try to loop over student exams(these exams exist in database) I don't get any output. `student.Exams` is an empty collection, but EF should have load it. – monoh_ Mar 22 '16 at 16:07
  • @TomTom, @Rene Vogt, how is my question a duplicate of how to fix NRE? My problem is that EF Lazy loading doesn't work, not about `Exams` being null, because EF should itself initialize this collection. – monoh_ Mar 22 '16 at 16:09
  • @AlexanderDerck, initializing collection in constructor prevents from getting `NullReferenceException` but collection is empty even if in database I have exams with id of given student. I have read lots of similar questions but still wasn't able to get my code working. – monoh_ Mar 22 '16 at 17:26

2 Answers2

12

You didn't follow the rules to enable Entity framework to create proxies (required for lazy loading), which needs public access:

A custom data class must be declared with public access.

Make your Exam and Student public and it should work.

Alexander Derck
  • 11,742
  • 4
  • 43
  • 73
2

In c# if you don't declare access modifiers, It will accept it as internal by default.

You should declare you entity classes as public.

Secondly collections should return empty collection beside of null. So If a student doesn't have any exam, you should return empty collection. That's wyh you should change your Student Constructor also.

 public class Student
    {
        public Student()
        {
            Exams = new List<Exam>();
        }
    }

Edit: If you have ICollection or IList, ef returns empty collection. You should use this constructor, if you are using IEnumurable.

Erkan Demirel
  • 4,112
  • 1
  • 21
  • 40