【发布时间】:2019-07-22 17:04:43
【问题描述】:
考虑以下查询,该查询必须返回导演以及每部电影的电影数量和演员数量。如何使用 EF CORE 2.2 在 LINQ 中编写此代码?我需要 LINQ 来生成实际使用 GROUP BY 和 EF CORE 2.1 和转发中支持的 SQL 聚合的 SQL。
SELECT DirectorName, COUNT(m.MovieID), COUNT(a.ActorID)
FROM Directors d
LEFT OUTER JOIN Movies AS m ON m.DirectorID = d.DirectorID
LEFT OUTER JOIN Actors AS a ON a.MovieID = m.MovieID
WHERE d.DirectorID = 1
GROUP BY DirectorName
示例 LINQ 查询是基于答案构建的,并且确实给了我结果,但该查询只有一个 LEFT 联接,没有分组依据。输出表明 DefaultIfEmpty()、GroupBy 和 Count 无法翻译,将在本地进行评估。
var results =
(
from d in _moviesContext.Directors
join m in _moviesContext.Movies on d.DirectorId equals m.DirectorId
into grpM from movies in grpM.DefaultIfEmpty()
join a in _moviesContext.Actors on movies.MovieId equals a.MovieId
into grpA from actors in grpA.DefaultIfEmpty()
where d.DirectorId == 1
group new { d, grpM, grpA } by new
{
d.DirectorName
} into grp
select new
{
DirectoryName = grp.Key.DirectorName,
MovieCount = grp.Sum(g => g.grpM.Count()),
ActorAcount = grp.Sum(g => g.grpA.Count())
}
).ToList();
LINQ 表达式 'DefaultIfEmpty()' 无法翻译,将被评估 本地。 Microsoft.EntityFrameworkCore.Query:警告:LINQ 无法翻译表达式“DefaultIfEmpty()”并将 当地评价。 Microsoft.EntityFrameworkCore.Query:警告: LINQ 表达式“来自 {[grpM] => DefaultIfEmpty()} 中的电影电影” 无法翻译,将在当地进行评估。 Microsoft.EntityFrameworkCore.Query:警告:LINQ 表达式 'GroupBy(new f__AnonymousType8
1(DirectorName = [d].DirectorName), new <>f__AnonymousType62(d = [d], grpM = [grpM]))' 不能 翻译并将在当地进行评估。 Microsoft.EntityFrameworkCore.Query:警告:LINQ 表达式 'DefaultIfEmpty()' 无法翻译,将被评估 本地。 Microsoft.EntityFrameworkCore.Query:警告:LINQ 无法翻译表达式“DefaultIfEmpty()”并将 当地评价。 Microsoft.EntityFrameworkCore.Query:警告: LINQ 表达式“来自 {[grpM] => DefaultIfEmpty()} 中的电影电影” 无法翻译,将在当地进行评估。 Microsoft.EntityFrameworkCore.Query:警告:LINQ 表达式 'GroupBy(new f__AnonymousType81(DirectorName = [d].DirectorName), new <>f__AnonymousType62(d = [d], grpM = [grpM]))' 不能 翻译并将在当地进行评估。 Microsoft.EntityFrameworkCore.Query:警告:LINQ 表达式 'Count()' 无法翻译,将在本地进行评估。 Microsoft.EntityFrameworkCore.Query:警告:LINQ 表达式 'Sum()' 无法翻译,将在本地计算。
这是模型
public partial class Directors
{
public int DirectorId { get; set; }
public string DirectorName { get; set; }
}
public partial class Movies
{
public int MovieId { get; set; }
public string MovieName { get; set; }
public int? DirectorId { get; set; }
}
public partial class Actors
{
public int ActorId { get; set; }
public string ActorName { get; set; }
public int? MovieId { get; set; }
}
【问题讨论】:
-
@Geekn 请包括查询中使用的实体模型。否则,我们对您的代码无能为力。
-
对不起...我知道原来的帖子有点多。我已经更新了它,我认为是一个更简单的问题。
-
原帖至少展示了您自己的努力,这表明您陷入了将 SQL 连接转换为 LINQ 连接的臭名昭著的陷阱。一个提示:使用导航属性,这一切都会容易得多。
-
可以编写翻译接近 SQL 查询的 LINQ 查询。但请注意,SQL
COUNT(MovieId)不是您可能想的那样 - 它基本上是COUNT(*)忽略了外部连接中的NULL值。但是加入 Actors(1 到多个)将多次计算电影,因此MovieCount无效。您可能需要的是 SQLCOUNT(DISTINCT MovieId),但它没有 LINQ 等效项,因此没有 EF Core 翻译。一般来说,EF Core 还没有为复杂的分组/聚合查询做好准备。
标签: c# linq entity-framework-core ef-core-2.2