【问题标题】:Entity Framework does not eager load when using Include()使用 Include() 时,实体框架不会急切加载
【发布时间】:2014-10-28 17:21:53
【问题描述】:

我有一个简单的模型和一个简单的查询。我正在尝试让 EF 急切加载我的导航属性:

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

问题在于这实际上并不急切加载DocType。奇怪的是排除 Include() 调用确实加载 DocType 属性,但是作为一个 查询。

我环顾四周并应用了我发现的每一个修复:

  1. 添加了对Include()的调用
  2. 从两个导航属性中删除了virtual

知道这里发生了什么吗?是否可以强制 EF 将其合并到一个预先加载的单个查询中?

编辑:这是我的数据模型:

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

最奇怪的是,当我打电话时:

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

DocType 属性已填充,但 EF 通过执行两个单独的查询来完成此操作。是否有可能以 EF 理解这可以通过一个查询来完成的方式进行设计?

编辑 2: This question 似乎解决了同样的问题,但只声明调用 Include() 修复了它,这在我的情况下不起作用。

【问题讨论】:

  • 它不急于加载 DocType 吗?或者它不是像您的 cmets 中提到的那样急切加载 DocType.Documents
  • 查询结果是Documents 的填充集合,其中DocType 属性设置为null。当我检查正在执行的 SQL 时,查询不包含关于 DocType 的任何内容,并且没有执行后续 SQL 来检索该数据。
  • 我无能为力,但我已经使用 EF 多年,从未见过这种行为。我希望你能找到解决办法。
  • 恐怕如果你的外键 ID 是 TypeId 并且你的外键引用是 DocType,它不符合约定。您是否正确地提到了这个流畅的 api .HasForeignKey(d =&gt; d.TypeId); 或在 TypeId 属性之上使用外键属性 [ForeignKey("DocType")]
  • 您需要包含您的实体定义,包括属性以及任何流畅的映射...否则我们不知道您的模型是如何定义的。

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


【解决方案1】:

要包含导航属性,我使用以下语法(在包含中使用引号):

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

【讨论】:

  • 您是说使用字符串而不是表达式更可取?不知何故,这似乎违背了将表达式作为选项的目的。
  • 我不是说什么是可取的。我只是说什么代码适合我。
【解决方案2】:

在一般情况下,使用字符串而不是表达式(如 @vanraidex 所述)不是一个好习惯。一般情况下。但是,当使用第三方提供程序(例如 Oracle 提供程序)时,它可能是获得正确 sql(使用连接)的唯一方法。

所以,如果你使用特殊的 Data Provider 并且 .Include() 方法不起作用,请尝试使用字符串而不是表达式。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    相关资源
    最近更新 更多