如果我有4k文件,为什么Func <t,bool>可以使用RavenDB查询,但是当我有800k文件时却没有?</t,bool>

时间:2014-05-01 11:53:16

标签: c# linq ravendb

如果我有4千个文件(可能还有更多文件,未检查过),我可以在Func<T,bool>中使用IDocumentSession.Query<T>().Where(...),我会得到预期的结果。但是,如果我有80万份文件,那么我必须使用Expression<Func<T,bool>>,否则我没有结果。

为什么这不一致?

问题是我有一个用于内存过滤器和数据库查询过滤器的谓词。对于内存中过滤器,集合为IEnumerable<T>,因此它使用Func<T,bool>,而对于数据库查询,集合为IQueryable<T>,因此它使用Expression<Func<T,bool>>。因此,在我的生产代码中,我有一个重载的“过滤器”方法 - 一个采用IEnumerable<T>而另一个采用IQueryable<T>。前者的内容为:return list.Where(getPredicate(x).Compile()),后者的内容为:return list.Where(getPredicate(x))

显然,这看起来像重复的代码,并大喊:“请重构我并减少代码重复”。但是一旦开发人员这样做,就应该打破单元测试。但是,在传递Func<T,bool>时,我无法让单元测试失败。

编辑:仔细检查后,它似乎与文件数量无关。如果我在单元测试中连接到相同的“生产”数据库(调用实际的生产代码),它会在使用Func<T,bool>时返回结果,但是当我运行应用程序时它什么都不返回。很奇怪!

1 个答案:

答案 0 :(得分:3)

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

如果使用Expression<Func<T, bool>>,则将在数据库级别应用Where子句,并且仅检索已过滤的元素。

修改: 这种行为是完全正确的#34;并且绝对可预测。

这2个Where是2种扩展方法。

Func的{​​{1}}作为参数。 IEnumerable<T>继承自IQueryable<T>。因此,如果您使用IEnumerable<T>作为参数,将采用此方法,并且在过滤之前将枚举Func