c# - 在按匿名类型分组的 Entity Framework 查询中选择分组键最终会为每个分组对象返回一个键

标签 c# sql-server linq entity-framework linq-to-sql

我有这张 table

ID        Name        City    ... more columns
----------------------------------------------
1         Nate        Boston  ...
2         John        Boston  ...
2         John        Boston  ...
3         Sam         Austin  ...

(由于我无法控制的原因,在某些情况下ID会重复)

我为此设置了一个 Entity Framework 模型,总的来说它工作得很好。我在尝试获取唯一列表时遇到问题。

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 提供程序。当我使用 EntityFramework 通过程序集连接 LinqPad 时,我得到了与真实项目中相同的结果。

我错过了什么导致 Entity Framework 和 Linq-To-SQL 对于同一查询返回不同的结果,如何获得与 Linq-To-SQL 相同的结果?

我应该指出,在 LinqPad 中,如果我删除 .Select(g => g.Key); 结果将按预期显示在快速 View 中(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]

这是从 Entity Framework 生成的 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 问题,我认为它一定是 Entity Framework 的问题,与 ID 的比较出错有关,因为存在重复。

我使用 Linq-To-Objects 重新编写了查询,如下所示,并且确实得到了预期的结果。这里的关键是在 .ToList() 之后执行 .GroupBy(...) ,以便在内存中比较值,其中使用 C# 规则而不是数据库或 Entity Framework 比较规则。

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)

我假设这是某种 Entity Framework 优化(Linq-To-SQL 不这样做),在我的重复 ID 的情况下会发生回火。

由于无论如何我都需要枚举所有返回的数据,因此 .ToList() 调用对我来说并不是那么糟糕。不过,我的表相当宽,因此我执行了额外的 .Select(t => new { ... }) 来减少从数据库服务器返回的列数,因为我不会从惰性中受益在 .ToList() 之后加载。

关于c# - 在按匿名类型分组的 Entity Framework 查询中选择分组键最终会为每个分组对象返回一个键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23944345/

相关文章:

sql - 从count大于1的地方删除,但保留一行

c# - 将 Microsoft Word 智能引号转换为直引号

sql - 使用 SQL XPATH 查询获取 XML 元素名称和属性值

Java,SQLSERVER语法

c# - FindAll 与 Where

c# - Linq 生成给定日期范围内缺失记录的列表

C# 枚举 VS 可空属性名称冲突

c# - 无法终止 Silverlight 中的工作线程

c# - 使用SSRS和SSIS自动化Excel输出c#

c# - 如何将项目添加到 Mock DbSet(使用 Moq)