C#中Lambda表达式类型Expression不接受lambda函数
在EF Core中我们经常会用System.Linq.Expressions系统命名空间的Expression<TDelegate>类型来作为EF Core的查询条件,比如:
using EFLambdaExpression.Entities;
using System;
using System.Linq;
using System.Linq.Expressions; namespace EFLambdaExpression
{
class Program
{
static void Main(string[] args)
{
using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
{
Expression<Func<User, bool>> userExperssion = u => u.UserCode != null; var users = dbContext.User.Where(userExperssion).ToList();
} Console.WriteLine("Press key to quit...."); Console.ReadLine();
}
}
}
但是如果我们将Expression<Func<User, bool>> userExperssion = u => u.UserCode != null改为Expression<Func<User, bool>> userExperssion = u => { return u.UserCode != null; }那么C#会报错,提示:
A lambda expression with a statement body cannot be converted to an expression tree
所以Expression<Func<User, bool>> userExperssion不能接受带函数体的u => { return u.UserCode != null; }这种lambda函数,它只支持简单的lambda表达式u => u.UserCode != null
虽然Expression<Func<User, bool>> userExperssion右边的lambda表达式中可以使用自定义函数,但是不建议这么做,因为这么做会导致EF Core对数据库表做全表查询
比如我们先执行下面的代码:
using EFLambdaExpression.Entities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Linq.Expressions; namespace EFLambdaExpression
{
class Program
{
static void Main(string[] args)
{
using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
{
Expression<Func<User, bool>> userExperssion = u => EF.Functions.Like(u.UserCode, "%ADMIN%"); var users = dbContext.User.Where(userExperssion).ToList();
} Console.WriteLine("Press key to quit...."); Console.ReadLine();
}
}
}
可以从EF Core的日志中看到生成了如下SQL语句:
=============================== EF Core log started ===============================
Executed DbCommand (122ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [u].[ID], [u].[CompanyCode], [u].[CreateTime], [u].[DataStatus], [u].[FirstName], [u].[LastName], [u].[MailAddress], [u].[MiddleName], [u].[Password], [u].[UserCode], [u].[Username]
FROM [MD].[User] AS [u]
WHERE [u].[UserCode] LIKE N'%ADMIN%'
=============================== EF Core log finished ===============================
因为EF.Functions.Like方法是EF Core定义的系统函数,所以我们看到EF Core可以将该C#方法转换为SQL查询中的LIKE语句作为查询的WHERE条件。
如果现在我们将EF.Functions.Like的调用放到我们自定义的一个C#方法UserCodeLike中去,然后在Expression<Func<User, bool>> userExperssion右边的lambda表达式中调用自定义方法UserCodeLike,代码如下所示:
using EFLambdaExpression.Entities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Linq.Expressions; namespace EFLambdaExpression
{
class Program
{
static bool UserCodeLike(User user, string pattern)
{
return EF.Functions.Like(user.UserCode, pattern);
} static void Main(string[] args)
{
using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
{
Expression<Func<User, bool>> userExperssion = u => UserCodeLike(u, "%ADMIN%"); var users = dbContext.User.Where(userExperssion).ToList();
} Console.WriteLine("Press key to quit...."); Console.ReadLine();
}
}
}
可以从EF Core的日志中看到生成了如下SQL语句:
=============================== EF Core log started ===============================
Executed DbCommand (124ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [u].[ID], [u].[CompanyCode], [u].[CreateTime], [u].[DataStatus], [u].[FirstName], [u].[LastName], [u].[MailAddress], [u].[MiddleName], [u].[Password], [u].[UserCode], [u].[Username]
FROM [MD].[User] AS [u]
=============================== EF Core log finished ===============================
可以看到,虽然最后查出来的结果是一样的,但是这次EF Core对User表做了全表查询,在SQL的查询语句中没有生成任何WHERE条件,说明EF Core不认识我们定义的UserCodeLike方法,不知道怎么将UserCodeLike方法转换为对应的SQL语句,所以干脆就做了全表查询,将User表的数据从数据库全查出来后,再调用我们的UserCodeLike方法来过滤数据,如果User表的数据量非常大,这样效率其实会非常低。所有不建议在EF Core的lambda表达式中使用自定义函数。
C#中Lambda表达式类型Expression不接受lambda函数的更多相关文章
- 委托、匿名委托、Lambda 表达式、Expression表达式树之刨根问底
本篇不是对标题所述之概念的入门文章,重点在阐述它们的异同点和应用场景.各位看官,这里就不啰嗦了,直接上代码. 首先定义一个泛型委托类型,如下: public delegate T Function&l ...
- C# Lambda表达式详解,及Lambda表达式树的创建
最近由于项目需要,刚刚学完了Action委托和Func<T>委托,发现学完了委托就必须学习lambda表达式,委托和Lambda表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介 ...
- 死磕Lambda表达式(二):Lambda的使用
城市就是森林,每一个男人都是猎手,每一个女人都是陷阱.--<三体> 在哪使用Lambda表达式? 在上一篇文章(传送门)中介绍了Lambda表达式的基本语法,其中的举了一个Lambda表达 ...
- 获取lambda表达式类型,获取attributes是注意事项
1.获取lambda表达式的MemberExpression所属类的类型,要使用:m.Expression.Type 而不要使用 m.Member.DeclaringType: 后者获取的是实际定 ...
- Lambda表达式 和 Expression<T>
经常用的Lambda表达式 返回的是 Expression<T> 格式 public class ActivityService { private readonly List<A ...
- C++中的动态类型与动态绑定、虚函数、运行时多态的实现
动态类型与静态类型 静态类型 是指不需要考虑表达式的执行期语义,仅分析程序文本而决定的表达式类型.静态类型仅依赖于包含表达式的程序文本的形式,而在程序运行时不会改变.通俗的讲,就是上下文无关,在编译时 ...
- mysql中的timestamp类型时间比较:unix_timestamp函数
在mysql中,某字段的类型设置为了timestamp,那么我们现在希望取出指定时间段的记录,该如何做呢? 在php中有time()和strtotime()来进行日期和时间戳的格式化,而在mysql中 ...
- 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types
匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...
- .NET中那些所谓的新语法之三:系统预定义委托与Lambda表达式
开篇:在上一篇中,我们了解了匿名类.匿名方法与扩展方法等所谓的新语法,这一篇我们继续征程,看看系统预定义委托(Action/Func/Predicate)和超爱的Lambda表达式.为了方便码农们,. ...
随机推荐
- python6
集合-set 集合是高中数据中的一个概念. 确定的一堆无需数据,集合中的买个数据称为一个集合 集合的定义 1.创建空集合 变量 = se ...
- NodeJS require路径
项目需要用nodejs,感觉nodejs是前端装逼神器了,是通向全栈工程师的必经之路哇,接下来开始踏上学习nodejs的征程.下面是第一个hello,world的程序. 1.server.js文件,这 ...
- 软件项目技术点(7)——在canvas上绘制自定义图形
AxeSlide软件项目梳理 canvas绘图系列知识点整理 图形种类 目前我们软件可以绘制出来的形状有如下这几种,作为开发者我们一直想支持用户可以拖拽的类似word里面图形库,但目前还没有找到比 ...
- js常用代码-笔记
1.字符串截取substr(str,length)返回从指定位置开始,截取length长度的子字符串.substring(start,end)返回从start开始到end结束的字符串.end不写就到结 ...
- hdu 1087 Super Jumping! Jumping! Jumping!(最大上升子序列和)
Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 ...
- Android GridView设置行数
普通的做法是设置一个高度,然后里面能显示出来几行就是几行,如果里面的内容高度变了,就需要重新调整高度来适配. 观察了一下它的onMeasure @Override protected void onM ...
- mybatis ${}使用注意事项
${key}有值, ${key,jdbcType=VARCHAR}没有值 总结:${}使用时不要指定jdbcType等属性,指定这些反而取不到值,这也是跟#{}的一个区别.以上只是开发中遇到的情况,具 ...
- android启动应用
private void openApp(String packageName) { PackageInfo pi = getPackageManager().getPackageInfo(packa ...
- ORACLE 角色授权
直接例子: 1.CREATE USER 用户名 identified by 密码 default tablespace 表空间名;GRANT CONNECT TO 用户名; GRANT RESOURC ...
- 求n的元素的最大最小值
public static int[] maxMin(int a[]) { int[] res = new int[2]; int len = a.length; if (len <= 0) { ...