GroupBy 表达式翻译失败

kab*_*178 6 entity-framework entity-framework-6 ef-core-3.0 .net-core-3.1

//Model
public class Application
{
    [Key]
    public int ApplicationId { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime ConfirmedDate { get; set; }
    public DateTime IssuedDate { get; set; }
    public int? AddedByUserId { get; set; }
    public virtual User AddedByUser { get; set; }
    public int? UpdatedByUserId { get; set; }
    public virtual User UpdatedByuser { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string TRN { get; set; }
    public string EmailAddress { get; set; }
    public string Address { get; set; }
    public int ParishId { get; set; }
    public Parish Parish { get; set; }
    public int? BranchIssuedId { get; set; }
    public BranchLocation BranchIssued { get; set; }
    public int? BranchReceivedId { get; set; }
    public BranchLocation BranchReceived {get; set; }
}

public async Task<List<Application>> GetApplicationsByNameAsync(string name)
{
    if (string.IsNullOrEmpty(name))
        return null;
    return await _context.Application
        .AsNoTracking()
        .Include(app => app.BranchIssued)
        .Include(app => app.BranchReceived)
        .Include(app => app.Parish)
        .Where(app => app.LastName.ToLower().Contains(name.ToLower()) || app.FirstName.ToLower()
        .Contains(name.ToLower()))
        .GroupBy(app => new { app.TRN, app })
        .Select(x => x.Key.app)
        .ToListAsync()
        .ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

上述GroupBy表达式在 VS Studio 中编译失败。我的目标是运行一个查询,按包含用户给定字符串的名称过滤结果,然后它应该按相似的TRN数字对结果进行分组,返回这些应用程序的列表以返回到视图。我想我真的很接近,但似乎无法弄清楚查询的最后一点。任何指导表示赞赏。

出现错误

InvalidOperationException: The LINQ expression 'DbSet<Application>
.Where(a => a.LastName.ToLower().Contains(__ToLower_0) || a.FirstName.ToLower().Contains(__ToLower_0))
.GroupBy(
source: a => new {
TRN = a.TRN,
app = a
},
keySelector: a => a)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()
Run Code Online (Sandbox Code Playgroud)

更新 看来这肯定是由于最近更新以来 .net core 3.x 和 EF core 一起运行的方式发生了变化。我不得不使用AsEnumerable()而不是将其更改为客户评估ToListAsync()。Steve py 给出的其余查询适用于此方法。即使在阅读了文档之后,我也不知道 groupby 在 LINQ 中是如何工作的,所以这对我帮助很大。然而,将查询传递给客户端评估可能会产生性能问题。

Ist*_*ckl 7

EF core 中的 GroupBy 支持就是一个笑话。

这在 EF6 的服务器上完美运行

var nonUniqueGroups2 = db.Transactions.GroupBy(e => new { e.AccountId, e.OpeningDate })
    .Where(grp => grp.Count() > 1).ToList();
Run Code Online (Sandbox Code Playgroud)

在 EF core 中,它会导致异常“无法转换给定的 'GroupBy' 模式。在 'GroupBy' 之前调用 'AsEnumerable' 以在客户端对其进行评估。” 该消息具有误导性,请勿致电,AsEnumerable因为这应该在服务器上处理。

我在这里找到了解决方法。额外的Select会有帮助。

                var nonUniqueGroups = db.Transactions.GroupBy(e => new { e.AccountId, e.OpeningDate })
                    .Select(x => new { x.Key, Count = x.Count() })
                    .Where(x => x.Count > 1)
                    .ToList();
Run Code Online (Sandbox Code Playgroud)

该解决方法的缺点是结果集不包含组中的项目。

存在 EF Core问题。请对其进行投票,以便他们真正解决此问题。


Ste*_* Py 1

基于此:

我想按 TRN 进行分组,TRN 是一组重复的数字,例如 12345,在应用程序表中可能有许多具有相同序列的记录,我只想要每组 TRN 序列中的最新行。

我相信这应该满足您的需求:

return await _context.Application
    .AsNoTracking()
    .Include(app => app.BranchIssued)
    .Include(app => app.BranchReceived)
    .Include(app => app.Parish)
    .Where(app => app.LastName.ToLower().Contains(name.ToLower()) || app.FirstName.ToLower()
    .Contains(name.ToLower()))
    .GroupBy(app => app.TRN)
    .Select(x => x.OrderByDescending(y => y.CreatedAt).First())
    .ToListAsync()
    .ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

GroupBy表达式应该代表您想要分组的内容。就您而言,TRN。当我们进行选择时,x代表每个“组”,其中包含属于每个 TRN 的可枚举应用程序集。因此,我们按 CreatedAt 日期降序排列它们,以使用 来选择最新的First

试一试。如果这不完全是您想要的,请考虑向您的问题添加一个示例集,以及所需的输出与此处产生的输出/错误。

  • 该错误表明表达式中的某些内容 EF Core 无法转换为 SQL。我认为这可能是 EF Core 3 中的重大更改,因为我已经测试了 EF Core 2.6 和 EF 6 中的表达式,并且它们转换得很好。如果您将 SQL Server 作为数据库运行,则无需使用额外的 ToLower() 进行字符串比较,前提是使用默认的不区分大小写的排序规则。我尝试将我的测试项目从 2.6 更新到 3.0,但由于模型构建器中的一些重大更改,它对我的​​实体配置产生了很大的影响。在我看来,EF Core 团队是一个功能失调的混乱...... (2认同)