无法翻译 LINQ 表达式(通用 class)
The LINQ expression could not be translated (Generic class)
我在 SO 上看到了很多这样的问题,但是其中 none 确实对我有帮助,所以我决定 post 另一个问题,尝试修复我的问题。
我有一个class GenericRepository<T>
作为基本CRUD
方法的模板,因为我有一个比较大的模型包,所以我不想实现对不同的 class 重复相同的方法(不要重复自己)。
当我尝试使用 Predicate<T>
创建用于查询的自定义方法时出现了问题。
这是我的代码:
public IEnumerable<T> GetMatching(Predicate<T> condition)
=> dbContext.Set<T>.Where(entity => condition(entity));
在我看来,这样做的目的是能够传递任何类型的查询,对其进行评估并作为结果返回。
这是我尝试通过使用名为 EmployeeID
:
的字段过滤来获取一些 Doctor
对象的部分
Repository.GetMatching(doctor => doctor.EmployeeID > 10);
我的想法是,返回一份医生列表,其中 EmployeeID
数字字段大于 10。
不幸的是,这给了我以下错误:
Unhandled exception. System.InvalidOperationException: The LINQ expression 'DbSet<Doctor>
.Where(d => Invoke(__condition_0, d[Doctor]))' 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().
根据错误信息,我尝试在GetMatching()
函数的末尾添加ToList()
,但仍然失败,同样的错误信息。
我错过了什么?
取 Expression<Func<T, bool>>
而不是 Predicate
,然后直接传入:
public IEnumerable<T> GetMatching(Expression<Func<T, bool>> condition)
=> dbContext.Set<T>.Where(condition);
原因是 Entity Framework 依赖表达式树来确定如何将 LINQ 代码转换为 SQL 查询。当它正在评估的表达式(你传递给 Where 的 lambda)调用一个 Entity Framework 不知道如何翻译的函数(就像有人传递给你的函数的任意委托)时,它会阻塞。
附带说明一下,请注意以下事实:返回 IEnumerable<T>
会使添加到返回值的任何其他 LINQ 代码都被视为 LINQ-to-Objects,而不是被 Entity Framework。如果这是您想要的,请考虑调用 .ToList()
并返回类似 IReadOnlyCollection<>
的内容以避免不必要地延迟执行。如果没有,考虑返回 IQueryable<>
.
我在 SO 上看到了很多这样的问题,但是其中 none 确实对我有帮助,所以我决定 post 另一个问题,尝试修复我的问题。
我有一个class GenericRepository<T>
作为基本CRUD
方法的模板,因为我有一个比较大的模型包,所以我不想实现对不同的 class 重复相同的方法(不要重复自己)。
当我尝试使用 Predicate<T>
创建用于查询的自定义方法时出现了问题。
这是我的代码:
public IEnumerable<T> GetMatching(Predicate<T> condition)
=> dbContext.Set<T>.Where(entity => condition(entity));
在我看来,这样做的目的是能够传递任何类型的查询,对其进行评估并作为结果返回。
这是我尝试通过使用名为 EmployeeID
:
Doctor
对象的部分
Repository.GetMatching(doctor => doctor.EmployeeID > 10);
我的想法是,返回一份医生列表,其中 EmployeeID
数字字段大于 10。
不幸的是,这给了我以下错误:
Unhandled exception. System.InvalidOperationException: The LINQ expression 'DbSet<Doctor>
.Where(d => Invoke(__condition_0, d[Doctor]))' 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().
根据错误信息,我尝试在GetMatching()
函数的末尾添加ToList()
,但仍然失败,同样的错误信息。
我错过了什么?
取 Expression<Func<T, bool>>
而不是 Predicate
,然后直接传入:
public IEnumerable<T> GetMatching(Expression<Func<T, bool>> condition)
=> dbContext.Set<T>.Where(condition);
原因是 Entity Framework 依赖表达式树来确定如何将 LINQ 代码转换为 SQL 查询。当它正在评估的表达式(你传递给 Where 的 lambda)调用一个 Entity Framework 不知道如何翻译的函数(就像有人传递给你的函数的任意委托)时,它会阻塞。
附带说明一下,请注意以下事实:返回 IEnumerable<T>
会使添加到返回值的任何其他 LINQ 代码都被视为 LINQ-to-Objects,而不是被 Entity Framework。如果这是您想要的,请考虑调用 .ToList()
并返回类似 IReadOnlyCollection<>
的内容以避免不必要地延迟执行。如果没有,考虑返回 IQueryable<>
.