【问题标题】:Entity Framework doesn't populate collection properties实体框架不填充集合属性
【发布时间】:2018-07-03 19:12:47
【问题描述】:

我遇到的问题与这些问题中提到的问题非常相似:

Why is Entity Framework navigation property null?

Why EF navigation property return null?

在我的例子中,情节扭曲是导航集合属性由 EF 填充,但仅在我查询了 DbContext 中依赖类型的 DbSet<T> 属性之后。为了让我的情况更清楚,我的模型是这样设置的:

[Table(nameof(Composer))]
internal class ComposerRelationalDto : RelationdalDtoBase
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    public virtual ICollection<NameRelationalDto> LocalizedNames { get; set; } = new HashSet<NameRelationalDto>();

    public virtual ICollection<ArticleRelationalDto> Articles { get; set; } = new HashSet<ArticleRelationalDto>();
}

[Table(nameof(ComposerName))]
internal class NameRelationalDto : RelationdalDtoBase
{
    [Key]
    public long Id { get; set; }

    [Required]
    [ForeignKey(nameof(Composer))]
    public Guid Composer_Id { get; set; }

    public ComposerRelationalDto Composer { get; set; }
}

[Table(nameof(ComposerArticle))]
internal class ArticleRelationalDto : RelationdalDtoBase
{
    [Key]
    public long Id { get; set; }

    [Index]
    public Guid StorageId { get; set; }

    [Required]
    [ForeignKey(nameof(Composer))]
    public Guid Composer_Id { get; set; }

    public ComposerRelationalDto Composer { get; set; }

    [Required]
    [MaxLength(5)]
    public string Language { get; set; }
}

在相应的存储库中,我按名称过滤 ComposerRelationalDto 对象:

DbContext.Set<NameRelationalDto>().Where(nameWhereClause).GroupBy(n => n.Composer_Id).Select(group => group.FirstOrDefault().Composer)

ComposerRelationalDtos 的集合对于 ArticlesLocalizedNames 属性具有空集合,即使数据已正确保存在数据库中。但是,如果我在 QuickWatch while debugging 中加载所有类型为 ArticleRelationalDtoNameRelationalDto 的 DTO,那么相同的过滤器将不再返回空集合,并且所有相关对象都存在于集合属性中

到目前为止,我尝试过的是

  1. 显式启用延迟加载和创建代理

  2. 手动配置一对多关系:

    modelBuilder.Entity<ComposerRelationalDto>().HasMany(c => c.LocalizedNames).WithRequired(n => n.Composer).HasForeignKey(n => n.Composer_Id);
    modelBuilder.Entity<ComposerRelationalDto>().HasMany(c => c.Articles).WithRequired(a => a.Composer).HasForeignKey(a => a.Composer_Id);
    
  3. 最后我只是尝试摆弄 DbQuery&lt;T&gt;.Include() 方法 DbContext.Set&lt;ComposerRelationalDto&gt;().Include(c =&gt; c.Articles),不幸的是它从它调用的内部方法之一抛出了 ArgumentNullException。

基本上,我尝试过的任何修复或解决方法都没有帮助,所以我必须寻求更多帮助。

编辑: 我将依赖类型的 Composer 属性修改为虚拟的。但是,问题仍然存在。

使用.Select(group =&gt; group.FirstOrDefault().Composer).Include(c =&gt; c.Articles).Include(c =&gt; c.LocalizedNames) 后,我现在不再获得ArgumentNullException(也许我获得ArgumentNullException,因为我最初在QuickWatch 中使用.Include()?),而是MySqlException:未知列' Join2.Id' in '字段列表';数据字典包含键:“服务器错误代码”值:1054。此外,the generated SQL 大得离谱,几乎难以辨认。

【问题讨论】:

  • 嗯.. 这真是个泡菜。我有一些猜测,但我不得不说 .Include() 引发异常的事实似乎是正在发生的事情的一个重要线索。它根本不应该。考虑使用该错误中的任何更多相关信息更新您的问题(如果有)。看看 DbContext.Set().SelectMany(c => c.Articles).Load() 会产生什么也会很有趣。
  • 能否包含完整的异常文本?有一个异常 /w a .Include() 语句可能会揭示有关映射的某些信息。一个细节是 Composer 属性也应该是 Virtual 以允许 EF 关联代理。另外,这是完整的映射吗? Composer 端没有模型构建器?在旁注中,后缀“Dto”对于实体来说相当具有误导性。 DTO 意味着数据传输,这将是一个基本的 POCO 类,用于将信息从您的域中继到 DbContext 范围之外的外部消费者(API 客户端、视图等)。
  • @Classe 在文章 DTO 集上使用 .Load() 会导致 Articles 属性被填充,就像调用 .ToArray() 时所做的一样
  • @StevePy 我用更多信息更新了这个问题。此外,模型构建器中与 Composer DTO 相关的唯一映射已经包含在内。文章和名称没有任何额外的 Fluent API 配置。 (实际上我确实有一个与域模型分开的关系数据库模型;因此 Dto 后缀在我的解决方案的上下文中是合适的。)
  • 那么...你怎么知道它们是空的?启用延迟加载后,EF 在(几乎)明确告知之前不会对数据库执行任何查询。例如,如果您在其中一个集合上调用 .ToList() ,是否有可能实际上有数据? .ToList() 将对为您准备的查询调用一个操作,并要求它执行它并返回将从数据库中检索的响应。 (您可能仍然有一些映射错误,并且分组看起来......很奇怪。但如果加载正常,它应该超出范围)

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


【解决方案1】:

我想通了。它是类声明上的 internal 访问修饰符。很遗憾,因为我真的想让解决方案的其余部分完全与数据库无关(因此首先不寻常地将 DTO 用于代码,而不是实际实体,正如 cmets 中已经指出的那样)并且我想强制执行这一点以严格的方式。

不管怎样,我用访问修饰符玩了更多,我只能通过使用internal protected 构造函数来限制 DB 对象的可见性。涉及internal 的类和ctor 可见性的任何其他组合都会导致问题再次出现。 InternalsVisibleTo 也没有运气。

这个问题 - Entity Framework Code First internal class - is it possible? - 似乎表明使用内部类对 EF 来说应该不是问题,但它似乎毕竟是个问题。如果不是那时(Julie Lerman 的回答可以追溯到 2011 年),那就是现在。我目前使用的是 EF 6.2.0。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多