在按匿名类型分组的实体框架查询中选择分组键,最终将为每个分组对象返回一个键

本文关键字:对象 返回 一个 实体 框架 查询 选择 类型 | 更新日期: 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()之后的延迟加载中获益。