我有以下枚举:
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,但是我还没有想到。做这个的最好方式是什么?
在link中确实得到了很好的解释,为什么它可以在.net core 2.1中运行。似乎,在以前的版本中,当EF Core无法将作为查询一部分的表达式转换为SQL或参数时,它会自动在客户端上评估该表达式。
这真的很糟糕。因为,如上所述:
例如,Where()调用中无法转换的条件可能导致表中的所有行从数据库服务器,以及要在客户端上应用的过滤器。因此,似乎以前您只是将所有数据加载到客户端,然后在客户端应用过滤器。
因此,您的代码存在的问题是,Func无法转换为Sql。要么将所有数据显式提取到应用中,然后进行过滤,要么使用第二版代码。
Context.Work.ToList()
.Where( w => w.IsHighValueWork());
但是,我不建议使用该版本。最好使用第二个版本。但是,您可以在枚举中使用标志,以使代码更具可读性和可维护性。