MrMelodie
MrMelodie

Reputation: 63

Entity framework - Include() loads all chidren properties even virtual ones

I am trying to build a model with Entity Framework - Code First in which I use a "Exam" class and a "Subject" class that have a many-to-many relationship.
A "Exam" contains a list of "Subject" (Subjects).
A "Subject" contains a list of "Exam" (Exams).

Both "Exams" and "Subjects" are virtual properties.

When I use context.Exams.Include("Subjects").ToList();, I get all the exams and all the subjects related to each exam, which is OK. The problem is I also get all the exams related to the subjects.

Result :

  1. Exam 1
    • Subject 1
      • Exam 3
      • Exam 4
    • Subject 2
      • Exam 3
  2. Exam 2 ...


In this particular case, I don't need the exams related to the subjects. I just need the following data :

  1. Exam 1
    • Subject 1
    • Subject 2
  2. Exam 2 ...


Is there a way to include "Subjects" but without the "Exams" property ?


Thank you.

Function

public List<Exam> GetAllExams()
    {
        using (var context = new PedagogieContext())
        {
            return context.Exams.Include("Subjects").ToList();
        }
    }

Classes

public class Exam
{
    public int Id { get; set; }
    public string ExamLabel { get; set; }
    public virtual List<Subject> Subjects { get; set; }
}

public class Subject
{
    public int Id { get; set; }
    public string SubjectLabel { get; set; }
    public virtual List<Exam> Exams { get; set; }
}

Mappings

class SubjectMap : EntityTypeConfiguration<Subject>
{
    public SubjectMap()
    {
        this.HasKey(e => e.Id);
        this.Property(e => e.Id).HasColumnName("KeyDiscipline");
        this.Property(e => e.SubjectLabel).HasColumnName("DisciplineLib");
        this.ToTable("vpDisciplines");
    }
}

class ExamMap : EntityTypeConfiguration<Exam>
{
    public ExamMap()
    {
        this.HasKey(e => e.Id);
        this.Property(e => e.Id).HasColumnName("KeyExamen");
        this.Property(e => e.ExamenLabel).HasColumnName("ExamenLib");
        this.ToTable("vExamens");

        this.HasMany(e => e.Subjects)
            .WithMany(d => d.Exams)
            .Map(m =>
            {
                m.ToTable("vrExamensDisciplines");
                m.MapLeftKey("KeyExamen");
                m.MapRightKey("KeyDiscipline");
            });

    }
}

Context

public class PedagogieContext : DbContext
{
    public PedagogieContext()
        : base(ConnectionStringManager.GetConnectionString())
    {
        this.Configuration.LazyLoadingEnabled = false;
    }

    public DbSet<Exam> Exams { get; set; }
    public DbSet<Subject> Subjects { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ExamMap());
        modelBuilder.Configurations.Add(new SubjectMap());
    }
}

Upvotes: 3

Views: 133

Answers (2)

MrMelodie
MrMelodie

Reputation: 63

Thank you all for your answers.
Indeed, entity framework doesn't load more exams than expected. It just populates the sub-exams with the exams already loaded.
My problem was actually a circular reference serializer issue. I chose to use DTO (with automapper) to specify exactly the data I need in my view.

http://cpratt.co/using-automapper-getting-started/

Upvotes: 1

Gert Arnold
Gert Arnold

Reputation: 109109

The "problem" is that Entity Framework executes relationship fixup whenever you get data from the database (and on many more occasions). This is the process where EF automatically populates navigation properties (like Subject.Exams) of entities in its cache.

You are fetching exams and subjects and EF kindly populates their Subjects and Exams, respectively. There is no way to stop EF from doing this (some may think that setting Configuration.AutoDetectChangesEnabled = false will do that, but no).

Note that you don't get more exams from the database than you get from the query, if that's what you're worried about. It's just that EF also creates the associations. In a debug view you could expand the collections endlessly without ever hitting the database.

The solution is not to display Subject.Exams. If this is for serialization, you have to block circular references. Some serializers (like Json.Net) have settings to do that.

Upvotes: 2

Related Questions