如何使用 Entity Framework Core 2.1 查询多对多关系?
How do you query a many-to-many relationship using Entity Framework Core 2.1?
我正在尝试使用 EF Core(Code First)select 来自多对多关系的数据,但出现以下错误:
Unhandled Exception: System.ArgumentException: must be reducible node
我认为我没有做任何特别奇怪的事情,我可以愉快地 运行 在 LinqPad 中使用 LinqToSQL 进行相关查询。希望有人能指出我哪里出错了?
我在控制台应用程序中创建了一个最小的(人为的)复制品,可以找到 here. Basically I have modelled the many to many relationship using a joining table as 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; }
}
我想从 Bar
对象创建 Value
的查找,使用 Foo
的 Id
作为键,使用以下 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]
The LINQ expression 'from <>f__AnonymousType02 <generated>_0 in {from FooBar fb in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable
1[ReducibleNodeDemo.FooBar]) join Bar fb.Bar in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[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)}' could not be translated and will be evaluated locally.
我对 EF Core 比较陌生,但多年来一直使用 EF6,并且从未遇到过像这样的简单查询的问题!
显然您遇到了当前的 EF Core 实现错误,因此请考虑将其报告给他们的问题跟踪器。
好像是SelectMany
里面的Select
和内部lambda里面使用了外参数f
造成的。解决方法是对元素选择器使用 SelectMany
重载:
.SelectMany(f => f.FooBars, (f, fb) => new { f.Id, fb.Bar.Value })
我相信当您使用等效的 LINQ 查询语法时,C# 编译器会使用它
(from f in this.context.Foos
from fb in f.FooBars
select new { f.Id, fb.Bar.Value })
在这种特殊情况下,另一个 workaround/solution 是直接从 FooBar
开始查询(具有显式连接实体的多对多的优点之一)
this.context.Set<FooBar>()
.Select(fb => new { fb.Foo.Id, fb.Bar.Value });
我正在尝试使用 EF Core(Code First)select 来自多对多关系的数据,但出现以下错误:
Unhandled Exception: System.ArgumentException: must be reducible node
我认为我没有做任何特别奇怪的事情,我可以愉快地 运行 在 LinqPad 中使用 LinqToSQL 进行相关查询。希望有人能指出我哪里出错了?
我在控制台应用程序中创建了一个最小的(人为的)复制品,可以找到 here. Basically I have modelled the many to many relationship using a joining table as 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; }
}
我想从 Bar
对象创建 Value
的查找,使用 Foo
的 Id
作为键,使用以下 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] The LINQ expression 'from <>f__AnonymousType0
2 <generated>_0 in {from FooBar fb in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable
1[ReducibleNodeDemo.FooBar]) join Bar fb.Bar in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[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)}' could not be translated and will be evaluated locally.
我对 EF Core 比较陌生,但多年来一直使用 EF6,并且从未遇到过像这样的简单查询的问题!
显然您遇到了当前的 EF Core 实现错误,因此请考虑将其报告给他们的问题跟踪器。
好像是SelectMany
里面的Select
和内部lambda里面使用了外参数f
造成的。解决方法是对元素选择器使用 SelectMany
重载:
.SelectMany(f => f.FooBars, (f, fb) => new { f.Id, fb.Bar.Value })
我相信当您使用等效的 LINQ 查询语法时,C# 编译器会使用它
(from f in this.context.Foos
from fb in f.FooBars
select new { f.Id, fb.Bar.Value })
在这种特殊情况下,另一个 workaround/solution 是直接从 FooBar
开始查询(具有显式连接实体的多对多的优点之一)
this.context.Set<FooBar>()
.Select(fb => new { fb.Foo.Id, fb.Bar.Value });