在按匿名类型分组的实体框架查询中选择分组键,最终将为每个分组对象返回一个键
本文关键字:对象 返回 一个 实体 框架 查询 选择 类型 | 更新日期: 2023-09-27 18:05:54
我有这个表
ID Name City ... more columns
----------------------------------------------
1 Nate Boston ...
2 John Boston ...
2 John Boston ...
3 Sam Austin ...
(由于我无法控制的原因,ID在某些情况下是重复的)
,我有一个实体框架模型设置,一般来说,它的工作很好。我有一个问题,而试图获得一个唯一的列表。
var result = db.table.GroupBy(t => new
{
ID = t.ID,
Name = t.Name,
City = t.City
}).Select(g => g.Key)
问题是,这个查询返回以下内容:
ID Name City
-----------------------------
1 Nate Boston
2 John Boston
2 John Boston
3 Sam Austin
我想我疯了,所以我启动了LinqPad,运行相同的查询,得到了我预期的结果:
ID Name City
-----------------------------
1 Nate Boston
2 John Boston
3 Sam Austin
我意识到,使用LinqPad,我使用Linq-To-SQL连接到我的数据库,而不是使用LinqPad的EntityFramework提供程序。当我通过我的程序集连接LinqPad时,使用EntityFramework,我得到与实际项目相同的结果。
我错过了什么是导致实体框架和Linq-To-SQL返回不同的结果为相同的查询和我怎么能得到相同的结果Linq-To-SQL?
我应该指出,在LinqPad中,如果我删除.Select(g => g.Key);
,结果将按预期显示在快速视图中(键在每个分组中是唯一的,并且2,John, Boston记录有两个子元素)。
作为参考,生成的SQL.
这是由Linq-To-SQL生成的SQL:
SELECT [t0].[ID], [t0].[Name], [t0].[City]
FROM [Table] AS [t0]
GROUP BY [t0].[ID], [t0].[Name], [t0].[City]
这是从实体框架生成的SQL:
SELECT
1 AS [C1],
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[City] AS [City]
FROM (SELECT
[Table].* -- I changed this to .* because EF code listed all column in table explicitly
FROM [dbo].[Table] AS [Table]) AS [Extent1]
@Gusman引导我找到解决方案。对于EntityKey问题让我认为它必须是一个实体框架的东西,与ID的比较出错有关,因为有重复。
我按照如下方式重写了查询,使用了link - to - objects,我确实得到了预期的结果。这里的关键是在.ToList()
之后执行.GroupBy(...)
,以便在内存中比较值,这里使用c#规则而不是数据库或实体框架比较规则。
var result = db.table
.Select(t =>
{
ID = t.ID,
Name = t.Name,
City = t.City
}) // project only used columns, to reduce data from db => web server
.ToList() // convert from Linq-To-Entities, to Linq-To-Objects
.GroupBy(t => new
{
ID = t.ID,
Name = t.Name,
City = t.City
})
.Select(g => g.Key)
我假设这是某种实体框架优化(Linq-To-SQL不做),在我的重复id的情况下是反向射击。
因为我需要枚举所有返回的数据,所以.ToList()
调用对我来说并不是那么糟糕。我的表非常宽,所以我执行了额外的.Select(t => new { ... })
来减少从数据库服务器返回的列数,因为我不会从.ToList()
之后的延迟加载中获益。