Entity Framework 投影翻译失败GroupBy

Entity Framework Projection translation failure GroupBy

我一直在清理一些实体 LINQ 方法查询,以尝试优化项目中生成的查询,并试图通过 GROUP BY 外键来避免 JOIN。但是 运行 与 Entity Framework 的意外投影失败。

使用 LINQPAD 7 中的演示数据库,这是原始查询的示例以及我如何尝试优化它。

作品:

Albums
    .Select(a => a.Tracks.OrderBy(t => t.Milliseconds).First())
    .Select(g => new { g.Name, g.Composer })
    .Dump();

运行时异常:

Tracks.GroupBy(t => t.AlbumId)
    .Select(g => g.OrderBy(t => t.Milliseconds).First())
    .Select(g => new { g.Name, g.Composer })
    .Dump();

现在我知道我可以执行以下操作,但它会产生一个非常奇怪的 SQL 查询(连接到自身)并且不像失败的示例那样清晰易读。

Tracks.GroupBy(t => t.AlbumId)
    .Select(g => g.OrderBy(t => t.Milliseconds).Select(g => new { g.Name, g.Composer }).First())
    .Dump();

谁能解释为什么 Entity Framework 不喜欢 GroupBy 后跟选择和投影?虽然与 table 的类似联接工作正常?

我正在寻找的最佳查询是:

SELECT Name, Composer
FROM (
    SELECT Name, Composer, ROW_NUMBER() OVER(PARTITION BY AlbumId ORDER BY Milliseconds) AS row
    FROM Track
)
WHERE row <= 1

我注意到,如果您更改查询顺序,则不会发生异常...

改变这个:

Tracks
    .GroupBy(t => t.AlbumId)
    .Select(g => g.OrderBy(t => t.Milliseconds).First())
    .Select(g => new { g.Name, g.Composer })
    .Dump();

有了这个:

Tracks
    .OrderBy(x => x.Milliseconds)
    .GroupBy(x => x.AlbumId)
    .Select(x => new { 
        x.FirstOrDefault().Name, 
        x.FirstOrDefault().Composer 
    })

我认为这是因为您试图在组内对列表进行排序,而您应该先对所有结果进行排序然后再进行分组,尽管我不完全确定。这个,如果不是 linq to sql,就可以正常工作。