首页 > 解决方案 > 使用 Group by 时无法翻译 LINQ 表达式

问题描述

我有一个使用 EF Core DB first 方法的 Asp.net 核心 Web API。我的 SQL Server 数据库中有以下表格。

我正在尝试获取给定 UserId 和 appId 的 RoleName 和功能列表。

以下是我到目前为止的 Linq 查询:

RoleDto role = 
    from a in ctx.Application.Where(x => x.ApplicationId == appId)
    from r in ctx.Role.Where(x => x.ApplicationId == a.ApplicationId)
    from ur in ctx.UserRole.Where(x => x.UserId == userId && x.RoleId == r.RoleId)
    from rf in ctx.RoleFeature.Where(x => x.RoleId == ur.RoleId)
    from f in ctx.Feature.Where(x => x.FeatureId == rf.FeatureId).Where(x => x.IsActive)
    group new { r.RoleName, f.FeatureId } by ur.RoleId into g
    select new RoleDto
    {
        Name = g.Select(x => x.RoleName).FirstOrDefault(),
        FeatureIds = g.Select(x => x.FeatureId).ToList()
    }.AsNoTracking()

但是,我收到一条错误消息,提示无法翻译 LINQ 表达式。

标签: linqasp.net-coreentity-framework-core

解决方案


  1. 您无需选择Application. 您可以从Role直接选择开始 -
from r in dbCtx.Role.Where(x => x.ApplicationId == appId)

这将简化 EF 生成的最终 SQL。所以查询会更快。

  1. 如果 aUser有多个Role,那么您正在尝试获取第一个。当您选择时,您应该这样做Role-
from r in ctx.Role.Where(x => x.ApplicationId == a.ApplicationId).Take(1)
  1. 最后,您可以获取 and 的列表RoleNameFeatureId然后在客户端进行分组 -
var query =
    from r in dbCtx.Role.Where(x => x.ApplicationId == appId).Take(1)
    from ur in dbCtx.UserRole.Where(x => x.UserId == userId && x.RoleId == r.RoleId)
    from rf in dbCtx.RoleFeature.Where(x => x.RoleId == ur.RoleId && x.Feature.IsActive)
    select new
    {
        RoleName = rf.Role.RoleName,
        FeatureId = rf.FeatureId
    };

var roleDto = query.AsNoTracking()
    .AsEnumerable()
    .GroupBy(p => p.RoleName)
    .Select(g => new RoleDto
    {
        Name = g.Key,
        FeatureIds = g.Select(p => p.FeatureId).ToList()
    })
    .FirstOrDefault();

推荐阅读