【发布时间】: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 的集合对于 Articles 和 LocalizedNames 属性具有空集合,即使数据已正确保存在数据库中。但是,如果我在 QuickWatch while debugging 中加载所有类型为 ArticleRelationalDto 和 NameRelationalDto 的 DTO,那么相同的过滤器将不再返回空集合,并且所有相关对象都存在于集合属性中。
到目前为止,我尝试过的是
显式启用延迟加载和创建代理
-
手动配置一对多关系:
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); 最后我只是尝试摆弄
DbQuery<T>.Include()方法DbContext.Set<ComposerRelationalDto>().Include(c => c.Articles),不幸的是它从它调用的内部方法之一抛出了 ArgumentNullException。
基本上,我尝试过的任何修复或解决方法都没有帮助,所以我必须寻求更多帮助。
编辑: 我将依赖类型的 Composer 属性修改为虚拟的。但是,问题仍然存在。
使用.Select(group => group.FirstOrDefault().Composer).Include(c => c.Articles).Include(c => 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