简体   繁体   中英

Entity Framework does not eager load when using Include()

I have a simple model and a simple query. I'm trying to get EF to eager load my navigation properties:

// Document object has a navigation property "DocType" of type DocType
// DocType object has a navigation property "Documents" of type ICollection<Documents> that is NOT virutal

context.Set<Document>().Where(d=>d.Id == id).Include(d=>d.DocType).SingleOrDefault();

The problem is that this doesn't actually eager load DocType . The stranger thing is that excluding the Include() call does load the DocType property, but as a second query.

I've looked all around and applied every fix I found:

  1. Added a call to Include()
  2. Removed virtual from both navigation properties

Any idea what's going on here? Is it possible to coerce EF to merge this into a single query that's eager loaded?

EDIT: This is my data model:

namespace Data.Models {

    class Document {
        public int Id { get; set;}
        public int TypeId { get; set; }
        public DocType DocType { get; set; }
    }

    class DocType {
        public int Id { get; set; }
        public string FullName { get; set; }
        public ICollection<Document> Documents { get; set; }
    }
}

namespace Data.Mappings {

    internal class DocumentTypeConfiguration : EntityTypeConfiguration<Document> {

        public DocumentTypeConfiguration() {
            ToTable("ProsDocs");

            HasKey(m => m.Id);

            Property(m => m.Id)
                .HasColumnName("ProsDocId")
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

            Property(m => m.TypeId)
                .HasColumnName("ProsDocTypeId")
                .HasMaxLength(3);

            HasRequired(d => d.DocType)
                .WithMany(dt=>dt.Documents)
                .WithForeignKey(d=>d.TypeId);
        }
    }

    internal class DocTypeTypeConfiguration : EntityTypeConfiguration<DocType> {

        public DocTypeTypeConfiguration() {
            ToTable("DocType");

            HasKey(m => m.Id);

            Property(m => m.Id)
                .HasColumnName("DocTypeId")
                .HasMaxLength(4);

            Property(m => m.FullName)
                .HasColumnName("DocTypeDesc")
                .HasMaxLength(255);
        }
    }
}

The oddest thing is that when I call:

context.Set<Document>().Find(id);

The DocType properties are populated, but EF does this by executing two separate queries. Is it possible to design this in such a way the EF understands that this can be accomplished with one query?

EDIT 2: This question seems to address the same problem, but only states the calling Include() fixes it, which is not working in my case.

To include navigation properties I use this syntax (with quotes in the Include):

context.Documents.Where(d=>d.Id == id). Include("DocType") .SingleOrDefault();

In general case, using string instead of expression (as mention @vanraidex) is not a good practice. In general case. However, when using third party providers (eg Oracle Provider) it can be the only way to get correct sql (with joins).

So, if you using special Data Provider and .Include() method doesn't work, try to use string instead of expression.

context.Documents.Where(d=>d.Id == id).Include("DocType").SingleOrDefault();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM