LINQ to 实体无法识别该方法

本文关键字:识别 方法 to 实体 LINQ | 更新日期: 2023-09-27 18:32:31

我写的这个查询失败了,我不确定为什么。

我正在做的是获取用户域对象的列表,将它们投影到视图模型,同时计算它们的排名,因为数据将显示在排行榜上。这就是我进行查询的想法。

 var users = Context.Users.Select(user => new
        {
            Points = user.UserPoints.Sum(p => p.Point.Value),
            User = user
        })
        .Where(user => user.Points != 0 || user.User.UserId == userId)
        .OrderByDescending(user => user.Points)
        .Select((model, rank) => new UserScoreModel
        {
            Points = model.Points,
            Country = model.User.Country,
            FacebookId = model.User.FacebookUserId,
            Name = model.User.FirstName + " " + model.User.LastName,
            Position = rank + 1,
            UserId = model.User.UserId,
        });
        return await users.FirstOrDefaultAsync(u => u.UserId == userId);

异常消息

System.NotSupportedException: LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[WakeSocial.BusinessProcess.Core.Domain.UserScoreModel] Select[<>f__AnonymousType0`2,UserScoreModel](System.Linq.IQueryable`1[<>f__AnonymousType0`2[System.Int32,WakeSocial.BusinessProcess.Core.Domain.User]], System.Linq.Expressions.Expression`1[System.Func`3[<>f__AnonymousType0`2[System.Int32,WakeSocial.BusinessProcess.Core.Domain.User],System.Int32,WakeSocial.BusinessProcess.Core.Domain.UserScoreModel]])' method, and this method cannot be translated into a store expression.

LINQ to 实体无法识别该方法

不幸的是,EF 不知道如何转换 Select 的版本,该版本采用具有两个参数(值和秩(的 lambda。

对于查询,两个可能的选项是:

  1. 如果行集非常小,则可以跳过在查询中指定位置,将所有 UserScoreModels 读入内存(使用 ToListAsync(,然后计算内存中位置的值

  2. 如果行集很大,您可以执行以下操作:

        var userPoints = Context.Users.Select(user => new
        {
            Points = user.UserPoints.Sum(p => p.Point.Value),
            User = user
        })
        .Where(user => user.Points != 0 || user.User.UserId == userId);
        var users = userPoints.OrderByDescending(user => user.Points)
        .Select(model => new UserScoreModel
        {
            Points = model.Points,
            Country = model.User.Country,
            FacebookId = model.User.FacebookUserId,
            Name = model.User.FirstName + " " + model.User.LastName,
            Position = 1 + userPoints.Count(up => up.Points < model.Points),
            UserId = model.User.UserId,
        });
    

请注意,这与我写的并不完全相同,因为两个总分并列的用户不会被任意分配不同的等级。如果需要,您可以重写逻辑以断开 userId 或其他度量值上的联系。这个查询可能不像您希望的那样漂亮和干净,但由于您最终只通过 userId 选择一行,希望它不会太糟糕。您还可以将排名查找和基本信息选择拆分为两个单独的查询,这可能会加快速度,因为每个查询都更简单。