我有数据库与翻译词典.它有"词"和"译"两个实体.每个翻译都链接到一个"源"字和一个"目标"字--例如,我可以用"cat"(英语)和"Kot"(波兰语)进行翻译,意思是"cat"翻译为"Kot","Kot"翻译为"cat".

当在词典中搜索给定的短语(例如"cat ")时,我想为这个短语和它被翻译成的所有单词获取Word个实体.因此,我开始的查询如下所示:

Word[] words = ctx.Words
  .Include(it => it.TranslationSrcWords) 
  .ThenInclude(it => it.SrcWord)
  .Include(it => it.TranslationDstWords)
  .ThenInclude(it => it.DstWord)
  ...

对于这样的代码,我得到了错误:

实体框架核心将自动修复先前加载到上下文实例中的任何其他实体的导航属性.

当然,上面的查询将导致单词重复--从开头(ctx.Words)取回一个,然后从SrcWordDstWord取回(翻译的一侧必须指向要找到的单词).

EF"优化"迫使我要么隐藏错误,要么注释掉嵌套的INCLUDE--在这两种情况下,它都会导致部分提取.例如,当我查找"cat "而不是得到如下翻译时:

("cat", "kot")

我得到的翻译如下:

("cat", null)

"cat"实际上是由EF和null修复的,因为我不得不跳过嵌套的INCLUDE,所以根本没有数据.

如何解决,即一次取数?

Full repo is here: 100 Simplified models:

public sealed class Word
{
    public long Id { get; set; }
    public string Phrase { get; set; } = null!;

    public  ICollection<Translation> TranslationDstWords { get; set; } = default!;
    public  ICollection<Translation> TranslationSrcWords { get; set; } = default!;
}

public sealed class Translation
{
    public long Id { get; set; }
    public long SrcWordId { get; set; }
    public long DstWordId { get; set; }

    public  Word DstWord { get; set; } = null!;
    public  Word SrcWord { get; set; } = null!;
}

推荐答案

您收到的错误是因为当您包括关系的一个导航端(集合或引用)时,EF Core会自动包括另一个导航端(也称为反向导航).

在你的样品中,两者

.Include(it => it.TranslationSrcWords) 
    .ThenInclude(it => it.SrcWord)

.Include(it => it.TranslationDstWords) 
    .ThenInclude(it => it.DstWord)

independently violate that rule 和 will cause the aforementioned exception.

你真正需要的是ThenInclude次航海other比逆行.例如:

.Include(it => it.TranslationSrcWords) 
    .ThenInclude(it => it.DstWord)

.Include(it => it.TranslationDstWords) 
    .ThenInclude(it => it.SrcWord)

这通常会在没有EF核心错误的情况下实现您所需的功能.

然而,在该特定情况下,两个多对一关系有效地形成单个多对多self关系.考虑到包含导航(同时包含IncludeThenInclude)自动包含反转,您可以很容易地看到,在查询中只包含上面的Include/ThenInclude请求中的一个就足够了.因为

Include(word => word.TranslationSrcWords)

自动包括translation.SrcWord.然后

ThenInclude(translation => translation.DstWord)

automatically includes translation.DstWord.TranslationDstWords, 和 the cycle is closed.

Shortly, for this example I would suggest including only one of the above Include / ThenInclude pairs. You can include both if you wish, 和 there won't be an error, but it would lead to much more inefficient SQL, 和 the result will be the same.

Csharp相关问答推荐

C#将参数传递给具有变化引用的变量

图形.DrawString奇怪异常的字距调整

C#使用属性和值将JSON转换为XML

通过EFCore上传大量数据.

FileStream. FlushAsync()是否确保文件被写入磁盘?

实体核心框架--HasColumnType和HasPrecision有什么不同?

WPF DataGrid中的三维数据

如何使用C#Interop EXCEL创建度量衡

Thad.Sept()vs Task.Delay().Wait()

N层解决方案上的依赖注入-删除样板

Azure Functions v4中的Serilog控制台主题

Blazor Server/.NET 8/在初始加载时调用异步代码是否冻结屏幕,直到第一次异步调用完成?

匿名类型的AbstractValidator

序列化过程中的死循环

毛伊岛.NET 8图片不再适合按钮

如何使用.NET 8.0中新的CompositeFormat类?

使用postman 测试配置了身份的.NET 6应用程序

使用LibraryImport在多个dll中导入相同的函数

外部应用&&的LINQ;左外部连接&类似于PostgreSQL的查询

使用c#中的Windows 10关机消息