【问题标题】:Using Function logic in LINQ Query net core 3在 LINQ Query net core 3 中使用函数逻辑
【发布时间】:2020-01-31 17:26:45
【问题描述】:

我有以下枚举:

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

还有一个班级

      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,但我还没有想到。做这个的最好方式是什么?

【问题讨论】:

    标签: c# .net-core linq-to-sql linq-to-entities


    【解决方案1】:

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

    link 很好地解释了为什么它在 .net core 2.1 中工作。似乎,在以前的版本中,当 EF Core 无法将作为查询一部分的表达式转换为 SQL 或参数时,它会自动评估客户端上的表达式。强>

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

    例如,无法转换的 Where() 调用中的条件可能会导致表中的所有行都从 数据库服务器,以及要在客户端应用的过滤器。

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

    所以,你的代码的问题是,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);
    

    【讨论】:

    • 你的方法有效,而且会让你大吃一惊。我看了下面的文章stackoverflow.com/questions/58630723/… 好像有一种使用表达式树的方法。如果没有更好的答案,我会将您标记为答案。
    • @user3097695 他们使用 expreions 动态构建 Func。对你来说,它不是必需的。正如我所说,EF 无法将 switch-case 转换为 sql
    • @FarhadJabiyev 我可以建议对您使用的 code-sn-p 进行一些小的更正吗? Context.Work.ToList().Where( w =&gt; w.IsHighValueWork()); 行应该是 Context.Work.ToList().Where( w =&gt; w.Type.IsHighValueWork());,因为扩展函数是为`WorkType` 类编写的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    相关资源
    最近更新 更多