在 LINQ Query net core 3 中使用函数逻辑

Using Function logic in LINQ Query net core 3

我有以下枚举:

      public enum WorkType
      {
        Type1,
        Type2,
        Type3,
        Type4,
        Type5,
        Type6
       }

和一个class

      public class Work {
        public WorkType Type {get; set;}
        ....
      }

和扩展方法:

    public static partial class WorkTypeExtensions
    {
      public static bool IsHighValueWork(this WorkType value)
      {
        switch (value)
        {
            case WorkType.Type1:
            case WorkType.Type2:
                return true;

            default:
                return false;
        }
      }
    }

和SQL Linq 查询

  public List<Work> GetHighValueWork()
  {
    var query = Context.Work.Where( w => w.IsHighValueWork());
    return query.ToList();
   }

这是我的问题的简化版本。此查询曾经有效,但在代码从 net core 2.1 转换为 3.1 后,它不再有效。错误消息是 无法翻译查询。要么以可翻译的形式重写查询,要么通过插入对 AsEnumerable()、AsAsyncEnumerable() 的调用显式切换到客户端评估。我不想将其更改为

 public List<Work> GetHighValueWork()
  {
    var query = Context.Work.Where( w => w.Type == WorkType.Type1 || w.Type == WorkType.Type2);
    return query.ToList();
   }

因为实际功能很复杂。我搜索了一下似乎可以使用 LINQ Expression Func,但我还没有想到。做这个的最好方式是什么?

IsHighValueWork 只是一个简单的 C# 方法。 EF 无法将该函数转换为 SQL。

link 中确实很好地解释了为什么它在 .net core 2.1 中工作。看起来,在以前的版本中,当 EF Core 无法将作为查询一部分的表达式转换为 SQL 或参数时,它会 自动计算表达式客户.

而且真的很糟糕。因为,如前所述:

For example, a condition in a Where() call which can't be translated can cause all rows from the table to be transferred from the database server, and the filter to be applied on the client.

因此,之前您似乎只是将所有数据加载到客户端,然后在客户端应用过滤器。

因此,您的代码存在问题,Func 无法转换为 Sql。 要么明确地将所有数据提取到应用程序中然后进行过滤,要么使用您的代码的第二个版本。

Context.Work.ToList()
       .Where( w => w.Type.IsHighValueWork());

但是,我不推荐使用那个版本。最好像这样使用第二个版本:

Func<Work, bool> IsHighValueWork = (work) =>
            work.Type == WorkType.Type1 || work.Type == WorkType.Type2;

然后:

var query = Context.Work.Where(IsHighValueWork);