为什么Func<;T、 bool>;如果我有4k个文档,但当我有800k个文档时不能使用RavenDB查询
本文关键字:文档 800k 不能 RavenDB 查询 4k lt Func bool 为什么 如果 | 更新日期: 2023-09-27 18:01:12
如果我有4000个文档(可能还有很多,还没有检查(,我可以在IDocumentSession.Query<T>().Where(...)
中使用Func<T,bool>
,并且我会得到预期的结果。但如果我有80万个文档,那么我必须使用Expression<Func<T,bool>>
,否则我不会得到任何结果。
为什么这不一致?
问题是,我有用于内存中过滤器和数据库查询过滤器的相同谓词。对于内存中的过滤器,集合是IEnumerable<T>
,因此它使用Func<T,bool>
,而对于数据库查询,集合是IQueryable<T>
,因此使用Expression<Func<T,bool>>
。因此,在我的生产代码中,我有一个重载的"filter"方法——一个方法采用IEnumerable<T>
,另一个方法使用IQueryable<T>
。前者的内容为:return list.Where(getPredicate(x).Compile())
,后者的内容为return list.Where(getPredicate(x))
显然,这看起来像是重复的代码,并大喊:"请重构我,减少代码重复"。但一旦开发人员这样做了,就应该破坏单元测试。然而,当通过Func<T,bool>
时,我不能让单元测试失败。
编辑:经过仔细检查,它似乎与文档数量无关。如果我在单元测试中连接到同一个"生产"数据库(调用实际的生产代码(,它在使用Func<T,bool>
时会返回结果,但在运行应用程序时不会返回任何结果。很奇怪!
好吧,在使用IQueryable
时使用Func<T, bool>
是一个非常糟糕的主意,因为这意味着你将从数据库中检索所有元素(因为你的Queryable将被枚举(,然后过滤器将应用于IEnumerable<T>
。
如果使用Expression<Func<T, bool>>
,则Where子句将应用于数据库级别,并且只检索经过筛选的元素。
编辑:这种行为是完全"正确"的,而且绝对可以预测。
这两个CCD_ 18是两个扩展方法。
具有Func
的一个以IEnumerable<T>
为自变量。CCD_ 21继承自CCD_。因此,如果使用Func
作为参数,则会采用此方法,并且在筛选之前会枚举Queryable
。