代码之家  ›  专栏  ›  技术社区  ›  Ben

如何使用EntityFrameworkCore2.1查询多对多关系?

  •  2
  • Ben  · 技术社区  · 7 年前

    未处理的异常:System.ArgumentException:必须是可还原节点

    我不认为我做了什么特别奇怪的事情,我可以很高兴地在LinqPad中使用LinqToSQL运行有问题的查询。希望有人能指出我错在哪里?

    我已经在控制台应用程序中创建了一个最小的(而且是人为的)复制品,可以找到 here . 基本上,我已经使用一个连接表为多对多关系建模 follows

    public class Foo
    {
        [Key]
        public int Id { get; set; }
    
        public ICollection<FooBar> FooBars { get; set; } = new List<FooBar>();
    }
    
    public class Bar
    {
        [Key]
        public int Id { get; set; }
    
        public string Value { get; set; }
    
        public ICollection<FooBar> FooBars { get; set; } = new List<FooBar>();
    }
    
    public class FooBar
    {
        [Required]
        public int FooId { get; set; }
    
        [ForeignKey(nameof(FooId))]
        public Foo Foo { get; set; }
    
        [Required]
        public int BarId { get; set; }
    
        [ForeignKey(nameof(BarId))]
        public Bar Bar { get; set; }
    }
    

    Value Bar 对象与 Id Foo 作为键使用以下命令 query :

    ILookup<int, string> data = 
        this.context.Foos
            .SelectMany(f => f.FooBars.Select(fb => new { f.Id, fb.Bar.Value }))
            .ToLookup(fb => fb.Id, fb => fb.Value);
    

    在出现错误之前,控制台中会出现以下警告:

    Microsoft.EntityFrameworkCore.Query[20500] LINQ表达式'from<&燃气轮机;匿名类型0 2 <generated>_0 in {from FooBar fb in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable 1[ReducibleNodeDemo.FooBar])在值中连接Bar fb.Bar(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable 1[ReducibleNodeDemo.Bar]) on Property([fb], "BarId") equals Property([fb.Bar], "Id") where ?= (Property([f], "Id") == Property([fb], "FooId")) =? select new <>f__AnonymousType0 2(Id=[f].Id,Value=[fb.Bar].Value)}'无法转换,将在本地计算。

    我对efcore还比较陌生,但是我已经在EF6工作了很多年,从来没有遇到过像这样简单的查询问题!

    1 回复  |  直到 7 年前
        1
  •  4
  •   Ivan Stoev    7 年前

    显然,您遇到了当前的EF核心实现错误,所以请考虑将其报告给他们的问题跟踪器。

    Select SelectMany 以及外部参数的用法 f 选择多个 元素选择器过载:

    .SelectMany(f => f.FooBars, (f, fb) => new { f.Id, fb.Bar.Value })
    

    我相信C编译器在使用等价的LINQ查询语法时会用到它

    (from f in this.context.Foos
     from fb in f.FooBars
     select new { f.Id, fb.Bar.Value })
    

    在这种特殊情况下,另一种解决方法/解决方案是直接从 FooBar (使用显式连接实体的多对多的优点之一)

    this.context.Set<FooBar>()
        .Select(fb => new { fb.Foo.Id, fb.Bar.Value });
    
    推荐文章