实体框架 - Include()加载所有子属性甚至虚拟属性

时间:2015-03-05 09:05:11

标签: c# entity-framework-6 code-first

我正在尝试使用Entity Framework构建一个模型 - Code First,其中我使用了一个“Exam”类和一个具有多对多关系的“Subject”类。
“考试”包含“主题”(主题)列表。
“主题”包含“考试”(考试)列表。

“考试”和“科目”都是虚拟属性。

当我使用context.Exams.Include("Subjects").ToList();时,我会参加所有考试和所有与每个考试相关的科目,这是可以的。问题是我也得到了与科目相关的所有考试。

结果:

  1. 考试1
    • 主题1
      • 考试3
      • 考试4
    • 主题2
      • 考试3
  2. 考试2 ...

  3. 在这种特殊情况下,我不需要与科目相关的考试。我只需要以下数据:

    1. 考试1
      • 主题1
      • 主题2
    2. 考试2 ...

    3.   

      有没有办法包含“主题”但没有“考试”属性?


      谢谢。

      功能

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

      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; }
      }
      

      映射

      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");
                  });
      
          }
      }
      

      上下文

      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());
          }
      }
      

2 个答案:

答案 0 :(得分:2)

“问题”是,无论何时从数据库获取数据(以及更多场合),实体框架都会执行 relationship fixup 。这是EF自动填充其缓存中实体的导航属性(如Subject.Exams)的过程。

您正在提取考试和科目,EF分别填写他们的Subjects Exams。没有办法阻止EF这样做(有些人可能认为设置Configuration.AutoDetectChangesEnabled = false会这样做,但没有。)

请注意,如果您担心这一点,那么您从数据库中获得的考试数量不会超过您从查询中获得的考试数。只是EF也创造了联想。在调试视图中,您可以无限制地扩展集合,而无需访问数据库。

解决方案不是显示Subject.Exams。如果这是用于序列化,则必须阻止循环引用。一些序列化程序(如Json.Net)有设置来做到这一点。

答案 1 :(得分:1)

谢谢大家的回答。
实际上,实体框架并没有加载比预期更多的考试。它只是填充了已经加载的考试的子考试。
我的问题实际上是一个循环引用序列化器问题。 我选择使用DTO(使用automapper)在我的视图中准确指定我需要的数据。

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