Reputation: 63
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 :
In this particular case, I don't need the exams related to the subjects. I just need the following data :
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
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
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