使用 Func 和 Expression Func 运行查询之间的区别 [重复]
Posted
技术标签:
【中文标题】使用 Func 和 Expression Func 运行查询之间的区别 [重复]【英文标题】:diffrence between running query with Func and Expression Func [duplicate] 【发布时间】:2019-01-03 03:55:06 【问题描述】:我一直在互联网上搜索Func和Expression Func之间的区别,不知何故我明白了,第一个只是一个函数获取数据然后将函数应用到内存中,但第二个,将其翻译为sql并在数据库中运行它,在我运行这两个查询之后:
public IEnumerable<T> SelectAll(Expression< Func<T, bool>> predicate)
return table.Where(predicate).ToList();
public IEnumerable<T> SelectAll(Func<T, bool> predicate)
return table.Where(predicate).ToList();
我把断点放在返回上,第一个返回12行,第二个返回1200行,谓词是:
s=>s.id="12345"
第二个,得到数据后应用谓词,我的问题是,我们在处理DB时通常应该使用表达式func吗?
【问题讨论】:
"但是第二个,把它翻译成 sql" 更精确地翻译成最终可以翻译成 SQL(或其他东西)的东西 虽然这两种方法中的代码看起来相同,但实际上调用的是不同的静态扩展Where
方法 - 来自 Queryable
和来自 Enumerable
。
【参考方案1】:
Func<T>
是一个委托,而 Expression<Func<T>>
是一个表达式。
表达式是一种抽象。
Expression<T>
可以编译成Func<T>
:
Expression<Func<int, int>> expr = a => a + 1;
Func<int,int> func = expr.Compile();
var res = func(1); // (1+1) = 2
因此,可以将表达式视为一种表示表达式的树。
这棵树是抽象的,你可以用它做很多事情。
那么当涉及到 SQL 时,我们如何利用这种行为呢?
您可以创建某人(实体框架)将转换为 SQL 的表达式。
所以当你有这样的表达时:
users.Where(u => u.Name.StartsWith("a"));
它可以被翻译成如下 SQL:
select * from Users where Name like 'a%'
由于有人编写了将表达式转换为 sql 的代码,因此它支持多种方法,但不是全部。因此,有时它会告诉您它无法将您的方法转换为 SQL,您必须提供 Expression<Func<T>>
或在 SQL 运行后运行该方法(使用 Linq to Objects)。
最重要的是,在大多数情况下,您更愿意使用表达式而不是 IQueryables,并使用将在数据库上运行的过滤器创建 SQL 查询,而不是获取大量数据库条目并在代码中过滤它们。
【讨论】:
【参考方案2】:我的问题是,我们在处理 DB 时通常应该使用表达式 func 吗?
是的,因为您希望向 SQL Server 提供尽可能多的信息,以便它可以优化数据库访问,并且您希望最大限度地减少从 SQL Server 返回的数据(删除所有不必要的数据,并聚合数据SQL Server 可以轻松聚合)因为将数据从 SQL Server 移动到 .NET 机器甚至是一项“工作”。
很明显,如果在 SQL 中很难做某事(如字符串操作),那么将其移至 .NET 是可以接受的。
请注意,使用 LINQ,您无法很好地控制生成的查询,这很容易成为“多级野兽”,您也无法确定查询的哪一部分将在 SQL 服务器上执行以及哪个部分会在本地执行(例如 EF Core 经常在本地执行 GROUP BY),也无法访问 SQL 的许多高级功能(例如所有的分区方法)。
【讨论】:
感谢您的精彩解释,所以根据您的说法,如果我做对了,想象一下我在这两种情况下的查询上都放了秒表,检索时间可能不同? @mortezasol 是的,但是只有当查询有点复杂,或者投影(选择)删除了很多列,或者 where 删除了很多行时,您才会看到区别......最后差异通常取决于 SQL 无法返回的数据量。以上是关于使用 Func 和 Expression Func 运行查询之间的区别 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Expression<Func<T,TResult>>和Func<T,TResult>
C# 如何将 Expression<Func<SomeType>> 转换为 Expression<Func<OtherType>>
Expression<Func<T,TResult>>和Func<T,TResult> 与AOP与WCF
组合表达式(Expression<Func<TIn,TOut>> 与 Expression<Func<TOut, bool>>)
如何从 Expression<Func<MyClass, string>> 动态创建 Expression<Func<MyClass, bool>> 谓