C# 编译谓词将在获取计数之前检索整个表

C# 编译谓词将在获取计数之前检索整个表,c#,sql,entity-framework,linq-to-sql,linq-to-entities,C#,Sql,Entity Framework,Linq To Sql,Linq To Entities,这在SQL端作为.Count()执行: account.SelectMany(acc => acc.Transactions).Count(t => !t.Disabled) 这将在获取计数之前检索整个表: private Expression<Func<Transaction, bool>> transactionsFilterPredicate = t => !t.Disabled; account.SelectMany(acc => acc

这在SQL端作为
.Count()
执行:

account.SelectMany(acc => acc.Transactions).Count(t => !t.Disabled)
这将在获取计数之前检索整个表:

private Expression<Func<Transaction, bool>> transactionsFilterPredicate = t => !t.Disabled;
account.SelectMany(acc => acc.Transactions).Count(this.transactionsFilterPredicate.Compile())
private Expression transactionFilterPredicate=t=>!t、 残疾人士;
account.SelectMany(acc=>acc.Transactions).Count(this.TransactionFilterPredicate.Compile())
为什么??我希望能够将谓词提取为变量。有没有办法做到这一点,并且仍然可以从SQL端操作中获益

编辑:


显然,删除代码的
.Compile()
部分可以解决问题。。。代码仍在编译(如
MSBuild
),并且计数在SQL端。
.Compile()
的好处是什么?

Compile
返回一个委托。不调用compile会将变量保留为
表达式
IQueryable
linq扩展方法接受表达式,而不是委托。底层提供程序可以通过访问(检查)表达式树的每个节点并转换为sql,将表达式转换为适当的sql。表达式是可以检查的数据结构。另一方面,
IEnumerable
上的扩展方法接受委托,不进行此类转换(因为它们不能)。它们将需要内存中的完整数据源(对于最后一个IQueryable调用而言已满)。。。
编译的好处在于,您可以创建可以调用的委托。表达式不能被调用,它们基本上只是数据。您可以动态生成表达式(例如,基于用户输入或其他变量),并将其转换为委托,然后可以调用该委托。