是否有可能获得IQueryable<>应用谓词时从EF集返回?

时间:2014-10-07 09:46:02

标签: c# predicates

似乎返回IEnumerable而不是IQueryable:

方法参数:Func<Cat, bool> predicate

代码:

var allCats = _catEntities.GetCats(); // IQueryable

if (skip.HasValue) allCats = allCats .Skip(skip.Value);
if (take.HasValue) allCats = allCats .Take(take.Value);

 if (predicate != null)
            {
                allCats = allCats.Where(predicate);
            }

这不会编译,因为.Where会返回IEnumerable而不是IQueryable。我知道我可以.AsQueryable或其他什么,但我怀疑它不会被视为正确的IQueryable

对此有简单的解决方法吗?

2 个答案:

答案 0 :(得分:2)

predicate参数应该是Expression<Func<Cat, bool>>,而不仅仅是Func<Cat, bool>

这样你获得IQueryable,因为你将使用Queryable.Where而不是Enumerable.Where。

在调用方法时,您仍然可以使用lambda表达式:编译器知道如何将lambda转换为Expression。

答案 1 :(得分:2)

问题是Func<Cat, bool>已经编译为.NET代码,因此无法在.NET进程之外执行。

因此,为了将谓词应用于allCats,必须执行allCats在此时定义的查询。正如您所推测的那样,使用AsQueryable只会包装返回的IEnumerable枚举。

如果希望LINQ提供程序翻译和执行谓词,则可以使用Expression<Func<Cat, bool>>。请注意,这将在IQueryable实现和谓词定义之间引入耦合。 (因为谓词必须是可以由LINQ提供程序执行的东西)。

使用lambda表达式,可以非常简单地定义Expression<Func<Cat, bool>>

Expression<Func<Cat, bool>> predicateExpression = c => c.Gender == Gender.Male;