【问题标题】:EF6 Linq Query .Include only returning first entry of child tableEF6 Linq 查询。仅包括返回子表的第一个条目
【发布时间】:2017-04-15 06:34:58
【问题描述】:

我想检索给定口袋妖怪的遭遇列表,因为口袋妖怪可以在很多地方遇到,所以我一直在尝试许多变体

var currentPokemon = _context.Pokemon
                                     .Where(mon => mon.Id == id)
                                     .Include(mon => mon.Encounters)
                                     .FirstOrDefault();

结果是一个包含所有相关数据的口袋妖怪对象,但只有第一次遭遇被检索并放入一个集合中,结果如下:

查看数据库,大约有 20 次与毛毛虫的遭遇,我想访问所有这些,但只能获得一个。

Pokemon 类的样子(省略不相关的字段):

[Table("pokemon")]
public partial class Pokemon {
    public Pokemon()
    {
        Encounters = new HashSet<Encounters>();
    }
    [Column("id")]
    public long Id { get; set; }
    [Required]
    [Column("identifier", TypeName = "VARCHAR(79)")]
    public string Identifier { get; set; }
    .
    .
    .

    [InverseProperty("Pokemon")]
    public virtual ICollection<Encounters> Encounters { get; set; }
 }

邂逅是什么样子的:

public partial class Encounters {
    .
    .
    .
    [ForeignKey("PokemonId")]
    [InverseProperty("Encounters")]
    public virtual Pokemon Pokemon { get; set; }
}

数据库数据:

我在这里误会了什么?

【问题讨论】:

  • 生成的sql是什么?上网看看如何获​​取sql查询
  • 你能显示db的记录吗?你指的是正确的数据库吗?
  • 您指的数据库是否正确?
  • 我无法使用全新的 DbContext 和最少的数据重现此行为。我按预期得到了口袋妖怪和遭遇。您未显示的代码中必须有其他内容。您发布的代码是可以的,并且您执行操作的顺序虽然不是最佳的,但确实会生成相同的 sql。

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


【解决方案1】:

我想是因为你打电话给.FirstOrDefault(),它只得到第一个项目。你可以省略它并添加.ToList()吗?此外,var currentPokemon 似乎不是一个好的变量名。你说你想要一个遭遇列表,对吧? var pokemonEncounters呢?

【讨论】:

  • 首先或默认将在口袋妖怪结果上完成,而不是遭遇
  • 弗雷杜所说的。省略 .FirstOrDefault() 只会返回一个长度为 1 的口袋妖怪数组,这是没有意义的,因为我只想得到 1 个口袋妖怪。至于我在寻找什么,这是一个单独的口袋妖怪,其中列出了该口袋妖怪的所有相关遭遇。用简单的英语,我想问“谁是 pokemon #10”并得到“Pokemon 10 是 Caterpie,你可以在以下地方找到 Caterpie:(地点列表)。”在最后添加.ToList() 会导致遭遇列表,但没有口袋妖怪。
  • 怎么样 var currentPokemon = _context.Pokemon .Where(mon => mon.Id == id) .Include(mon => mon.Encounters) .FirstOrDefault().Select(p => p .遭遇);
  • 你不能在.FirstOrDefault()返回的口袋妖怪对象上调用.Select()
  • @Fredou 和@Riwen - 你是对的。现在我想起来了,var currentPokemon = _context.Pokemon.Include(mon =&gt; mon.Encounters).FirstOrDefault(p =&gt; p.Id = id); 应该返回第一个带有遭遇列表的口袋妖怪。您应该能够使用currentPokemon.Encounters 访问遭遇。对吗?
【解决方案2】:

我认为问题在于您使用 ForeignKey 和 InverseProperty 设置关系的方式。

尝试重写为:

[Table("Pokemon")]
public class Pokemon
{
    public int Id { get; set; }
    public string Name { get; set; }

    [InverseProperty("Pokemon")]
    public ICollection<Encounter> Encounters { get; set; }

}

[Table("Enconters")]
public class Encounter
{
    public int Id { get; set; }

    public int PokemonId { get; set; }

    [ForeignKey("PokemonId")]
    public Pokemon Pokemon { get; set; }

}

【讨论】:

    【解决方案3】:

    抱歉,我一直在寻找错误的地方来寻找答案。在调试器中逐步完成后,我可以看到我的 Pokemon 查询确实返回了所需的结果:附加了许多遭遇的 pokemon。我的问题似乎出在其他地方(特别是:我看到的 JSON 化对象通过我的 Web 前端截断了遇到数组以仅包含第一个结果)。

    我将发布一个包含正确问题的新问题,并在发现问题后从此处链接到该问题。

    【讨论】:

    • 是的,在输出中发现一个 json 序列化错误。
    • 好的,所以问题是 JSON 序列化程序检测到自引用循环(因为 Pokemon 引用了 Encounters,而 Encounters 又引用了 pokemon)并在 Debug 输出中抛出了一个错误(我错过了重复)以避免进入无限循环。这个问题的解决方案在这里:stackoverflow.com/questions/17313632/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 2023-04-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多