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>区别的更多相关文章

  1. EF 底层封装方法(供参考)

    闲暇之余,整理了一下EF底层的一些基础方法,供查看,只有接口,具体实现需要你们自己写了. 建议:接口的实现定义为虚方法,当父类的方法不满住子类需求时,可以重写此方法 此接口都为公用方法,基本上满足小系 ...

  2. .net core Entity Framework 与 EF Core

    重点讲 Entity Framework Core ! (一)Entity Framework 它是适用于.NET 的对象关系映射程序 (ORM),现在的EF6已经是久经沙场,并经历重重磨难,获得一致 ...

  3. ef core自动映射

    原回答:https://stackoverflow.com/questions/26957519/ef-core-mapping-entitytypeconfiguration 一.反射 protec ...

  4. Expression<Func<TObject, bool>>与Func<TObject, bool>的区别

    Func<TObject, bool>是委托(delegate) Expression<Func<TObject, bool>>是表达式 Expression编译后 ...

  5. .NET Core中合并Expression<Func<T,bool>>的正确姿势

    这是在昨天的 .NET Core 迁移中遇到的问题,之前在 .NET Framework 中是这样合并 Expression<Func<T,bool>> 的: public s ...

  6. lambda表达式Expression<Func<Person, bool>> 、Func<Person, bool>区别

    前言: 自己通过lambda表达式的封装,将对应的表达式转成字符串的过程中,对lambda表达式有了新的认识 原因: 很多开发者对lambda表达式Expression<Func<Pers ...

  7. Expression<Func<T, bool>>与Func<T, bool>的区别

    转自:http://www.cnblogs.com/wow-xc/articles/4952233.html Func<TObject, bool>是委托(delegate) Expres ...

  8. expression<Func<object,Bool>> 及 Func<oject,bool>用法

    using System;using System.Collections.Generic;using System.Linq;using System.Linq.Expressions;using ...

  9. EF Core中避免贫血模型的三种行之有效的方法(翻译)

    Paul Hiles: 3 ways to avoid an anemic domain model in EF Core 1.引言 在使用ORM中(比如Entity Framework)贫血领域模型 ...

随机推荐

  1. 使用celery异步发送短信

    目录 1.使用celery异步发送短信 1.1在celery_task/mian.py中添加发送短信函数 1.2在verifcations/views.py中添加celery发送短信视图函数 1.3 ...

  2. C中memcpy函数用法

    1.函数原型 void *memcpy(void *destin,void *source,unsigned n); 其中, destin代表用于存储复制内容的目标数组,类型强制转换为void*指针. ...

  3. 一种更优雅的Flutter Dialog解决方案

    前言 系统自带的Dialog实际上就是Push了一个新页面,这样存在很多好处,但是也存在一些很难解决的问题 必须传BuildContext loading弹窗一般都封装在网络框架中,多传个contex ...

  4. Centos7 之间的文件拷贝

    环境: 内网了两台cenots7主机 scp命令 scp [参数] [原路径] [目标路径] scp -P 22022 /home/file.war root@192.168.253.172:/hom ...

  5. 老猿学5G专栏完结说明

    老猿学5G是因为工作原因促成的,主要目的是为了研究5G的计费架构相关内容,到今天为止,基本上达成目标,因此这个专栏基本上告一段落了. 回想这2个多月的日子,从一个对5G相关知识完全不熟悉的小白,到现在 ...

  6. PyQt(Python+Qt)学习随笔:QDockWidget停靠部件的setWidget和widget方法

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 QDockWidget对象由一个标题栏和内容区域组成.QDockWid ...

  7. 第11.1节 Python正则表达式概述

    正则表达式是可匹配文本片段的模式,一个正则表达式指定了一个与之匹配的字符串集合.最简单的正则表达式为普通字符串,与它自己匹配.如正则表达式'python'与字符串'python'匹配.通过匹配,可以在 ...

  8. csv文件的写操作

    import csv sumbmit_csv_path = "submit_have_valid_SGD.csv" with open(sumbmit_csv_path, &quo ...

  9. 关于EF框架EntityState的几种状态

    在使用EF框架时,我们通常都是通过调用SaveChanges方法把增加/修改/删除的数据提交到数据库,但是上下文是如何知道实体对象是增加.修改还是删除呢?答案是通过EntityState的枚举值来判断 ...

  10. mock.js 和easy-mock使用

    mock.js 1.项目中引入mock.js <script src="../static/js/mock.js" type="text/javascript&qu ...