在.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. HBase0.98使用ReplicationAdmin管理集群同步

    公司datalink平台负责从各种数据源读取数据并同步到其他的同步或者异构数据源,最近增加的HBase的reader利用到了Hbase的Replication特性. 正常情况下,我们配置HBase的R ...

  2. 嵌入式设计初体验:永远的hello,world

    目前,xilinx的zynq系列FPGA炒的火热,SOC成为FPGA发展的必然趋势.可见所有功能均用硬件描述语言设计是不科学的.硬件逻辑独有的并行性使其在实时处理和并行算法中占尽优势,但当执行串行操作 ...

  3. ES6 正则的扩展

    1. RegExp构造函数 ES5中,RegExp构造函数的参数: 参数是字符串,这时第二个参数表示正则表达式的修饰符(flag) 参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝.但是,ES ...

  4. JavaScript及jQuery中的各种宽高属性图解

    文/poetries(简书作者)原文链接:http://www.jianshu.com/p/60332df38393 著作权归作者所有,转载请联系作者获得授权, 并标注“简书作者”.   作者声明:本 ...

  5. 初学者福音——10个最佳APP开发入门在线学习网站

    根据Payscale的调查显示,现在的APP开发人员的年薪达到:$66,851.这也是为什么那么多初学的开发都想跻身到APP开发这行业的主要原因之一.每当你打开App Store时候,看着琳琅满目的A ...

  6. js随机数生成,生成m-n的随机数

    使用js生成n到m间的随机数字,主要目的是为后期的js生成验证码做准备,Math.random()函数返回0和1之间的伪随机数 var random = Math.random(); console. ...

  7. JavaScript的DOM编程--08--复习

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  8. Ubuntu下LAMP环境配置

    接下来是搭建个人学习环境,之前的随笔介绍了个人的网络配置,简单记录一下. 1. 安装apache: apt-get install apache2 2.  安装php5:apt-get install ...

  9. Ruby学习之对象模型

    这两周工作内容较多,平时自己也有点不在状态,学的东西有点少了,趁着现在还有点状态,赶紧复习一下之前学习的Ruby吧. Ruby是我真正开始接触动态语言魅力的第一个语言,之前虽然也用过且一直用perl. ...

  10. android开发文章收藏

    1.activity [Android的从零单排开发日记]之入门篇(四)——Android四大组件之Activity 两分钟彻底让你明白Android Activity生命周期(图文)! 2.serv ...