【问题标题】:IEnumerable and IQueryable - the best of both worldsIEnumerable 和 IQueryable - 两全其美
【发布时间】:2021-07-05 21:56:57
【问题描述】:

出于性能原因,我的许多服务现在都返回 IQueryable,因此调用者可以决定在具体化之前过滤哪些元素。出于设计原因(接口等),我宁愿返回 IEnumerables,但这肯定会消除 IQueryables 的优势:完整结果集的实现加上没有 -Async 方法。

我已经开始编写一些更喜欢 IQueryable 而不是 IEnumerable 的扩展方法,例如:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Expression<Func<TSource, bool>> predicate)
    => source is IQueryable<TSource> ? Queryable.Where(source as IQueryable<TSource>, predicate) : Enumerable.Where(source, predicate.Compile());

public static Task<TSource[]> ToArrayAsync<TSource>(this IEnumerable<TSource> source)
    => (source as IQueryable<TSource>)?.ToArrayAsync() ?? Task.FromResult(source.ToArray());

我不可能是唯一一个在想这个的人。这些方法有什么改进吗?那里已经有很好的收藏/解决方案了吗?或者这是一个糟糕的设计?所以请告诉我原因。

谢谢!

【问题讨论】:

  • 如果您要将其用作IQueryable,为什么要返回IEnumerable?它只会让正在发生的事情变得不那么明显。

标签: c# ienumerable iqueryable


【解决方案1】:

就我个人而言,这会让我变得谨慎;序列和查询是相似的,但又足够不同,我非常想确定它是如何处理的。在生成表达式树然后编译它时也有一些重要的开销,而不是在捕获上下文上使用直接编译器生成的方法。表达式树的开销是合理的,如果它将被用作查询组合和翻译的一部分,但在序列案例中不需要。

也许更明显的方法是在序列上使用AsQueryable() 来模拟真正的查询。

但是:我猜你所拥有的应该可以工作。作为一个小的语法说明,在最近的 C# 版本中,您可以将类型化的值捕获为 is 的一部分,以避免双重转换:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Expression<Func<TSource, bool>> predicate)
    => source is IQueryable<TSource> q ? Queryable.Where(q, predicate) : Enumerable.Where(source, predicate.Compile());

尝试Compile() 上的布尔标志可能也很有趣——使用解释模式会降低执行速度,但会避免生成 IL。它可能对小数据集产生积极影响,而对大数据集产生负面影响。

附带说明:可查询源有多种异步实现; EF Core 有一个,而 IX(Reactive 的一部分)有另一个。它们彼此不兼容并使用不同的方法,但两者都可以根据您的情况工作。

【讨论】:

  • 感谢您非常详细的回答!还有那个额外的代码糖!不知道-我喜欢!在我的“框架”中,有几个服务需要通过接口返回一个 IEnumerable,但只能返回一个 IQueryable。如果确实返回 IQueryable,我不希望所有调用者检查实际返回类型,而是采用性能最高的返回类型。因此,对于我的内部用例,您会说我的方法可以吗?除了额外的代码糖:)
  • @tris 它会工作的;其他一切都是完全主观的;可能会有一些开销,但这是否重要取决于上下文 - 所以:我们不能真正评论 - 但是:回到我的 AsQueryable 评论:那里的代码已经检查“is IQueryable-T”,老实说:我'只会使用 AsQueryable();引用:github.com/dotnet/runtime/blob/main/src/libraries/…(以及上面的几行通用版本)
  • 是的,谢谢 - 可能是最好的解决方案,实际上正是我想要的:weblogs.asp.net/zeeshanhirani/…
猜你喜欢
  • 2020-08-19
  • 2020-04-28
  • 1970-01-01
  • 2011-06-09
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多