在.Net开发中,Entity framework是微软ORM架构的最佳官方工具。我们可以使用Lambda表达式在Entity framework中DbSet<T>类上直接做查询(比如使用DbSet<T>类的Where、First、Count等查询函数)返回数据库结果实体。

不知道大家有没有注意到DbSet<T>类上的很多查询函数都有两种类型的重载,就拿Where这个查询函数举例:

一种是传入Func<Tsource, bool>委托作为参数


public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

这种Where函数的重载返回的是IEnumerable<TSource>集合类型。

调用的示例如下面代码所示:

//CustomerDbContext为Entity framework中的DbContext
using (var customerDbContext = new CustomerDbContext())
{
//显示Entity framework底层调用的Sql语句到Visual Studio的输出窗口
customerDbContext.Database.Log = (message) => {
Debugger.Log(, "Sql", message);
}; Func<Mid_TriaBalance, bool> func = r => r.ID == ;//使用lambda表达式查询ID为1的数据库数据
var triaBalance = customerDbContext.Mid_TriaBalance.Where(func).First();
}

我们在上面的代码中使用了DbContext的Log委托,显示Entity framework生成的底层Sql语句到Visual Studio,运行该代码,我们来看看生成的Sql语句是什么,结果如下截图:

结果让人大跌眼镜,我们发现实际上Entity framework生成的Sql没有包含任何Where条件,是将整张Mid_TriaBalance表的数据都返回到C#代码后,再过滤出ID等于1的这一行数据。这种方式当Mid_TriaBalance表的数据比较少的时候还好,但是一旦Mid_TriaBalance表的数据很大比如100万行,那么我们为了查询ID为1的这一行数据,就需要将Mid_TriaBalance表中的100万行数据从数据库中取出先放到内存中,再去筛选ID为1的这一行数据,效率低下可想而知,还有可能造成服务器内存溢出。

一种是传入Expression<Func<TSource, bool>>类型作为参数:


public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

这种Where函数的重载返回的是IQueryable<TSource>集合类型。

调用的示例如下面代码所示:

//CustomerDbContext为Entity framework中的DbContext
using (var customerDbContext = new CustomerDbContext())
{
//显示Entity framework底层调用的Sql语句到Visual Studio的输出窗口
customerDbContext.Database.Log = (message) => {
Debugger.Log(, "Sql", message);
}; Expression<Func<Mid_TriaBalance, bool>> exp = r => r.ID == ;//使用lambda表达式查询ID为1的数据库数据
var triaBalance = customerDbContext.Mid_TriaBalance.Where(exp).First();
}

同样我们在上面的代码中使用了DbContext的Log委托,显示Entity framework生成的底层Sql语句到Visual Studio,运行该代码,我们来看看生成的Sql语句是什么,结果如下截图:

这次我们看到Where函数使用Expression<Func<TSource, bool>>类型传入Lambda表达式后,Entity framework在底层生成了我们期望的Sql语句,包含了Where条件去限制数据库只查询ID为1的数据。很明显这种方式只会从数据库返回ID为1的一行数据到C#代码,效率和性能明显优于传入Func<Tsource, bool>委托的重载方式。

总结

我们可以看到这两种调用方式乍看之下觉得差别不大,最终都是返回Mid_TriaBalance表中ID为1的这一行数据。但是后台生成的Sql语句却有天壤之别,查询性能也有天壤之别。应该在Entity framework的Where、First、Count等查询函数中,避免使用传入Func<Tsource, bool>委托这种重载,因为这种重载在后台生的Sql语句中是不带任何Where限制条件的,是将整张表的数据先从数据库查出来后,放到C#代码内存中再做过滤,非常低效。

此外Expression<Func<TSource, bool>>类的构造函数无法直接调用,我们是无法去直接new一个Expression<Func<TSource, bool>>对象的,只有通过将lambda表达式直接赋值给Expression<Func<TSource, bool>>类型做隐式转换,C#会自动生一个Expression<Func<TSource, bool>>对象如下面代码所示:

Expression<Func<Mid_TriaBalance, bool>> exp = r => r.ID == ;//使用lambda表达式直接给Expression<Func<TSource, bool>>类型赋值,C#会帮助我们生成一个Expression<Func<TSource, bool>>对象

另外注意,不能将Func<TSource, bool>委托直接赋给Expression<Func<TSource, bool>>类型,这两种类型没法做类型转换,如下图所示,代码编译会报错:

Entity framework 中Where、First、Count等查询函数使用时要注意的更多相关文章

  1. entity framework 新手入门篇(3)-entity framework实现orderby,count,groupby,like,in,分页等

    前面我们已经学习了entityframework的基本的增删改查,今天,我们将在EF中实现一些更加贴近于实际功能的SQL方法. 承接上面的部分,我们有一个叫做House的数据库,其中包含house表和 ...

  2. [转]在Entity Framework中使用LINQ语句分页

    本文转自:http://diaosbook.com/Post/2012/9/21/linq-paging-in-entity-framework 我们知道,内存分页效率很低.并且,如果是WebForm ...

  3. Entity Framework 教程——Entity Framework中的实体类型

    Entity Framework中的实体类型 : 在之前的章节中我们介绍过从已有的数据库中创建EDM,它包含数据库中每个表所对应的实体.在EF 5.0/6.0中,存在POCO 实体和动态代理实体两种. ...

  4. Visual Studio Entity Framework (EF) 生成SQL 代码 性能查询

    Visual Studio Entity Framework (EF) 生成SQL 代码 性能查询     SQL 中,有SQL Server Profiler可以用来查询性能以及查看外部调用的SQL ...

  5. 关于Entity Framework中的Attached报错的完美解决方案终极版

    之前发表过一篇文章题为<关于Entity Framework中的Attached报错的完美解决方案>,那篇文章确实能解决单个实体在进行更新.删除时Attached的报错,注意我这里说的单个 ...

  6. Entity Framework学习笔记(六)----使用Lambda查询Entity Framework(1)

    请注明转载地址:http://www.cnblogs.com/arhat 在前几章中,老魏一直使用Linq来查询Entity Framework.但是老魏感觉,如果使用Linq的话,那么Linq的返回 ...

  7. Lazy<T>在Entity Framework中的性能优化实践

    Lazy<T>在Entity Framework中的性能优化实践(附源码) 2013-10-27 18:12 by JustRun, 328 阅读, 4 评论, 收藏, 编辑 在使用EF的 ...

  8. Entity Framework中的几种加载方式

            在Entity Framework中有三种加载的方式,分别是延迟加载,自动加载和显示加载.下面用一个例子来说明:现在有两个表,一个是资料表(Reference),另外一个表是资料分类表 ...

  9. 在Entity Framework 中实现继承关系映射到数据库表

    继承关系映射到数据库表中有多种方式: 第一种:TPH(table-per-hiaerachy) 每一层次一张表 (只有一张表) 仅使用名为父类的类型名的一张表,它包含了各个子类的所有属性信息,使用区分 ...

随机推荐

  1. HDFS租约实践

    一.租约详解 Why租约 HDFS的读写模式为 "write-once-read-many",为了实现write-once,需要设计一种互斥机制,租约应运而生租约本质上是一个有时间 ...

  2. php html5 文件上传 (原创)

    今天自己写了一个HTML5+FileReader+php 的文件上传,ajax异步上传也支持 git 下载:git clone https://github.com/jiechengyang/HTML ...

  3. 解决openssh漏洞,升级openssh版本

    关于解决漏洞的问题我就不详说了,主要就是升级版本.这里我们就直接简单记录下步骤: 1.升级 使用root用户登录系统进入到/home/guankong ,上传openssh-6.6p1.tar.gz到 ...

  4. win10下部署.Net Web项目到IIS10

    本问主要介绍如何将.Net Web项目部署到IIS10下面. 1.确保iis功能已开启 开启步骤如下:控制面板->程序 点击确定,ok,iis功能已开启. 2.打开iis,绑定站点到iis下面 ...

  5. cleanMyMac

    想看外国网站可以找我,facebook.youtube.XX大片等,只要8元钱,无限制用到服务器关闭.看大片流畅不成问题 需要cleanMyMac的请加微信只要10或直接拍 http://a.p6ff ...

  6. Java 并发编程:volatile的使用及其原理

    Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...

  7. 删除SVN版本信息的两种方式

    一.在linux下删除SVN版本信息 删除这些目录是很简单的,命令如下 find . -type d -name ".svn"|xargs rm -rf 或者 find . -ty ...

  8. NPOI 1.2.5 教程

    NPOI1.2.5教程官方地址 作者:Tony Qu & atao.xiang QQ群:20144214 ===== 持续更新中 ===== a. NPOI简介 b. 版权声明 目录 1. O ...

  9. Robot Framework 学习笔记(二)-------第一个脚本

    robot Framework环境搭建好之后先来一个简单的脚本跑一下 一.新建项目 二.新建测试套件  三.创建测试用例 四.导入Selenium2Library库 因为RF框架编写基于web 的测试 ...

  10. VMware虚拟机下为Ubuntu添加磁盘

    20G的磁盘还是不够用啊,正好复习下磁盘分区和逻辑卷. 关闭虚拟机,打开VMware,右键虚拟机点击设置,点下下方的添加,就可以添加磁盘了. 进入虚拟机,查看: root@ubuntu:/# fdis ...