为什么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>时会返回结果,但在运行应用程序时不会返回任何结果。很奇怪!

为什么Func<;T、 bool>;如果我有4k个文档,但当我有800k个文档时不能使用RavenDB查询

好吧,在使用IQueryable时使用Func<T, bool>是一个非常糟糕的主意,因为这意味着你将从数据库中检索所有元素(因为你的Queryable将被枚举(,然后过滤器将应用于IEnumerable<T>

如果使用Expression<Func<T, bool>>,则Where子句将应用于数据库级别,并且只检索经过筛选的元素。

编辑:这种行为是完全"正确"的,而且绝对可以预测。

这两个CCD_ 18是两个扩展方法。

具有Func的一个以IEnumerable<T>为自变量。CCD_ 21继承自CCD_。因此,如果使用Func作为参数,则会采用此方法,并且在筛选之前会枚举Queryable