英文:
Why is .Where acting as IEnumerable insteading of IQueryable?
问题
我实现了一个名为 WhereIf 的 IQueryable<T> 类型的扩展/助手,正如你从名称中猜到的那样,它仅在满足预条件时应用过滤,并通过代码在 EntityFramework 查询中链接,但它有两个问题,并且不起作用,而在另一个类似的实现中,它却正常工作。那么为什么第一个 .Where
不起作用,而第二个却正常工作呢?
public static class WhereIfHelper
{
public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, bool condition, Func<T, bool> expression)
where T: class
{
return condition ? source.Where(expression) : source;
}
}
.Where()
的类型是 IEnumerable<T>,这导致了运行时异常,所以我使用了.AsQueryable()
来解决它。- 当我调用它时,抛出了:
The source 'IQueryable' doesn't implement 'IAsyncEnumerable<Model>'. Only sources that implement 'IAsyncEnumerable' can be used for Entity Framework asynchronous operations.
我目前不知道如何解决这个问题。
在第二段代码中,我使用了引用类型而不是泛型,并且没有预条件。
public static class RepositoryIssueExtensions
{
public static IQueryable<Game> FilterGames(this IQueryable<Game> games,
DateTimeOffset initialDate,
DateTimeOffset lastDate) => games.Where(i => i.CreatedAt >= initialDate && i.CreatedAt <= lastDate);
}
这次 .Where
被识别为类型 IQueryable<T>。
英文:
I implemented an extension/helper called WhereIf of Type IQueryable<T>, as you may have guessed by the name of it, it applies the filtering only if a pre-condition is met and is chained in EntityFramework query by code, but there were two problems with it and didn't work, and in another similar implementation, it worked fine.
So why is that the first .Where
didn't work but the second works just fine?
public static class WhereIfHelper
{
public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, bool condition, Func<T, bool> expression)
where T: class
{
return condition ? source.Where(expression) : source;
}
}
.Where()
is of type IEnumarable<T> which caused a runtime exception, so I used.AsQueryable()
to solve it.- When I called it threw:
The source 'IQueryable' doesn't implement 'IAsyncEnumerable<Model>'. Only sources that implement 'IAsyncEnumerable' can be used for Entity Framework asynchronous operations.
Which I don't know how to solve at this moment.
In the second code, I used a reference type instead of a generic and without a pre-condition.
public static class RepositoryIssueExtensions
{
public static IQueryable<Game> FilterGames(this IQueryable<Game> games,
DateTimeOffset initialDate,
DateTimeOffset lastDate) => games.Where(i => i.CreatedAt >= initialDate && i.CreatedAt <= lastDate);
}
This time .Where
is recognized as type IQueryable<T>.
答案1
得分: 4
Enumerable.Where
接受 Func<>
谓词,而 Queryable.Where
需要对称的 Expression<Func<>>
,因为 IQueryable<T>
实现了 IEnumerable<T>
,在提供的代码中唯一适用的重载是针对 IEnumerable
的。将该方法更改为接受 Expression<Func<T, bool>>
(甚至参数名都是正确的):
public static class WhereIfHelper
{
public static IQueryable<T> WhereIf<T>(this IQueryable<T> source,
bool condition,
Expression<Func<T, bool>> expression)
where T: class
{
return condition ? source.Where(expression) : source;
}
}
P.S.
查询提供程序使用表达式树分析传递的方法,并将其转换为其他形式(例如 ORM 的 SQL)。了解更多:
英文:
Enumerable.Where
accepts Func<>
predicates while Queryable.Where
requires symmetrical Expression<Func<>>
's, since IQueryable<T>
implements IEnumerable<T>
the only suitable overloads in the provided code are for IEnumerable
. Change the method to accept Expression<Func<T, bool>>
(you even have right parameter name):
public static class WhereIfHelper
{
public static IQueryable<T> WhereIf<T>(this IQueryable<T> source,
bool condition,
Expression<Func<T, bool>> expression)
where T: class
{
return condition ? source.Where(expression) : source;
}
}
P.S.
Expression trees are used by queryable providers to analyze passed method and turn them into something else (like SQL in case of ORMs). Read more:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论