EF Core 封装方法Expression<Func<TObject, bool>>与Func<TObject, bool>区别
unc<TObject, bool>是委托(delegate)
Expression<Func<TObject, bool>>是表达式
Expression编译后就会变成delegate,才能运行。比如
Expression<Func<int, bool>> ex = x=>x < 100;
Func<int, bool> func = ex.Compile();
然后你就可以调用func:
func(5) //-返回 true
func(200) //- 返回 false
而表达式是不能直接调用的。
===========================
案例:不正确的查询代码造成的数据库全表查询。
//错误的代码
Func<QuestionFeed, bool> predicate = null;
if (type == 1)
{
predicate = f => f.FeedID == id && f.IsActive == true;
}
else
{
predicate = f => f.FeedID == id;
}
//_questionFeedRepository.Entities的类型为IQueryable<QuestionFeed>
_questionFeedRepository.Entities.Where(predicate);
上面代码逻辑是根据条件动态生成LINQ查询条件,将Func类型的变量作为参数传给Where方法。
实际上Where要求的参数类型是:Expression<Func<TSource, bool>>。
解决方法:
不要用Func<TSource, bool>,用Expression<Func<TSource, bool>>。
//正确的代码
Expression<Func<QuestionFeed, bool>> predicate=null;
if (type == 1)
{
predicate = f => f.FeedID == id && f.IsActive == true;
}
else
{
predicate = f => f.FeedID == id;
}
_questionFeedRepository.Entities.Where(predicate);
框架中加入了EF,使开发效率大大加快,但是项目做出来之后,数据稍微多一点,页面的加载速度就会非常慢。经过层层详细的排查之后,发现是项目封装的EF工具类有问题。
/// <summary>
/// 按条件查询
/// </summary>
/// <param name="whereLambda">lambda表达式</param>
/// <returns>IQueryable 泛型集合</returns>
public IQueryable<T> LoadItems(Func<T, bool> whereLambda)
{
return MyBaseDbContext.Set<T>().Where(whereLambda).AsQueryable();
}
方法的参数whereLambda,其类型为Func<T, bool> ,在调用LoadItems方法时,通过SQL Server Profiler检测生成的sql语句,你会发现它只生成了一条查询全部结果的语句。然后通过一步步断点调试发现,将数据全部加载完毕后,还会根据查询条件whereLambda进行很多次的循环,才能把最终结果返回。
并且当调用带条件参数的查询方法时,都会遇到这个问题。不过当发现问题之后,基本也就能解决问题了。随后我们发现了与Func<TObject, bool> 非常相似的类型Expression<Func<TObject, bool>>
Expression<Func<TObject, bool>>为表达式类型,它会带上查询条件一并生成sql语句,将查询结果返回,大大提高查询效率。
修改后的方法:
/// <summary>
/// 按条件查询
/// </summary>
/// <param name="whereLambda">lambda表达式</param>
/// <returns>IQueryable 泛型集合</returns>
public IQueryable<T> LoadItems(Expression<Func<T, bool>> whereLambda)
{
return MyBaseDbContext.Set<T>().Where(whereLambda).AsQueryable();
}

修改之后需要注意:
修改为表达式类型后按照之前的思路写可能会报错
LINQ to Entities 不识别方法“System.String ToString()”,因此该方法无法转换为存储表达式。
LINQ to Entities 不识别方法“…get_Item(Int32)”,因此该方法无法转换为存储表达式。
错误原因:
因为底层方法的参数Lambda,由委托类型改为表达式类型。因此咱们写的Lambda表达式里面不能存在C#的方法,比如 ToString()、ToInt()等等。因为表达式类型不能识别。
解决方案:
将Lambda中用到的参数,在外面定义成变量。然后再放到Lambda表达式中。
举例:
//修改之前
listQuestionTypeDetails = this.CurrentDal.LoadItems(u => u.ExamQuestionTypeEntity.QuestionTypeId == enQuestionType.QuestionTypeId.ToString()).ToList(); //修改之后
String questionTypeId = enQuestionType.QuestionTypeId.ToString(); listQuestionTypeDetails = this.CurrentDal.LoadItems(u => u.ExamQuestionTypeEntity.QuestionTypeId == questionTypeId ).ToList();
总结:Expression<Func<TObject, bool>>与Func<TObject, bool>
Func<TObject, bool> 委托类型,使用这个类型执行查询时会查询表中的全部数据,加载到内存中然后在根据条件循环进行筛选。
Expression<Func<TObject, bool>> 表达式类型,使用该类型作为参数时,会将查询条件一并添加到sql语句中查询出结果。
EF Core 封装方法Expression<Func<TObject, bool>>与Func<TObject, bool>区别的更多相关文章
- EF 底层封装方法(供参考)
闲暇之余,整理了一下EF底层的一些基础方法,供查看,只有接口,具体实现需要你们自己写了. 建议:接口的实现定义为虚方法,当父类的方法不满住子类需求时,可以重写此方法 此接口都为公用方法,基本上满足小系 ...
- .net core Entity Framework 与 EF Core
重点讲 Entity Framework Core ! (一)Entity Framework 它是适用于.NET 的对象关系映射程序 (ORM),现在的EF6已经是久经沙场,并经历重重磨难,获得一致 ...
- ef core自动映射
原回答:https://stackoverflow.com/questions/26957519/ef-core-mapping-entitytypeconfiguration 一.反射 protec ...
- Expression<Func<TObject, bool>>与Func<TObject, bool>的区别
Func<TObject, bool>是委托(delegate) Expression<Func<TObject, bool>>是表达式 Expression编译后 ...
- .NET Core中合并Expression<Func<T,bool>>的正确姿势
这是在昨天的 .NET Core 迁移中遇到的问题,之前在 .NET Framework 中是这样合并 Expression<Func<T,bool>> 的: public s ...
- lambda表达式Expression<Func<Person, bool>> 、Func<Person, bool>区别
前言: 自己通过lambda表达式的封装,将对应的表达式转成字符串的过程中,对lambda表达式有了新的认识 原因: 很多开发者对lambda表达式Expression<Func<Pers ...
- Expression<Func<T, bool>>与Func<T, bool>的区别
转自:http://www.cnblogs.com/wow-xc/articles/4952233.html Func<TObject, bool>是委托(delegate) Expres ...
- expression<Func<object,Bool>> 及 Func<oject,bool>用法
using System;using System.Collections.Generic;using System.Linq;using System.Linq.Expressions;using ...
- EF Core中避免贫血模型的三种行之有效的方法(翻译)
Paul Hiles: 3 ways to avoid an anemic domain model in EF Core 1.引言 在使用ORM中(比如Entity Framework)贫血领域模型 ...
随机推荐
- SpringSecurity之整合JWT
SpringSecurity之整合JWT 目录 SpringSecurity之整合JWT 1. 写在前面的话 2. JWT依赖以及工具类的编写 3. JWT过滤器 4. 登录成功结果处理器 5. Sp ...
- 对Tarjan——有向图缩点算法的理解
开始学tarjan的时候,有关无向图的割点.桥.点双边双缩点都比较容易地理解了,唯独对有向图的缩点操作不甚明了.通过对luoguP2656_采蘑菇一题的解决,大致搞清了tarjan算法的正确性. 首先 ...
- GraphicsLab 之 Atmospheric Scattering (二)
作者:i_dovelemon 日期:2020-11-25 主题:Atmospheric Scattering, Volume Scattering, Rayleigh Scattering, Mie ...
- CentOS下Mysql简易操作
Mysql mysql的root密码重置 编辑mysql主配置文件 vim /etc/my.cnf 添加..grant参数 [mysqld] skip-grant 重启mysql服务 service ...
- moviepy音视频剪辑:音视频的加载和输出
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 在本地进行音视频处理时,首先要从视频文件 ...
- PyQt(Python+Qt)学习随笔:QMainWindow的addDockWidget方法增加QDockWidget停靠窗到主窗口
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 DockWidget除了放在QMainWindow窗口内外,也可以放在 ...
- 第8.21节 Python中__lt__、__gt__等 “富比较”(“rich comparison”)方法用途探究
一. 富比较方法 Python的基类object提供一系列可以用于实现同类对象进行"比较"的方法,可以用于同类对象的不同实例进行比较.他们也是实例方法,定义如下: object.l ...
- Jmeter(三十二) - 从入门到精通 - Jmeter Http协议录制脚本工具-Badboy5(详解教程)
1.简介 这一篇文章,宏哥主要想讲解一下,录制完脚本不是就完事了,我们有时候还需要断言,看结果是否和我们预期的结果一致.这在测试中都是很重要的.用句老话说:只看结果不看过程. 2.录制脚本 想要断言, ...
- 补:冲刺Day1
各个成员在 Alpha 阶段认领的任务: 任务 执行人 用户模块 高嘉淳 订单模块 覃泽泰 商品模块 莫政.卢耀恒 充值模块 卢耀恒 前端界面设计&代码 许梓莹.梁小燕 发布博客 莫政 明日各 ...
- 半夜删你代码队 Day7冲刺
一.每日站立式会议 1.站立式会议 成员 昨日完成工作 今日计划工作 遇到的困难 陈惠霖 好友界面初步 完善好友界面 无 侯晓龙 帮助他人建立数据库 用户信息界面 无 周楚池 完善管理员界面 用户界面 ...