在.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. jsDOM编程-乌龟抓小鸡游戏

    <html> <head>  <title>js乌龟抓小鸡游戏 </title>    <meta http-equiv="conten ...

  2. Vue入门总结

    技术栈:VUE:Vue-router:Vue-resource:Vue-cli: 项目:个人博客vue重构 一.vue-cli脚手架搭建项目结构 全局安装vue-cli: npm install vu ...

  3. IT服务(运维)管理实施的几个要点--第二章 人员和组织架构

    子曰"没有合适的人" 在流程化的管理模式下,最容易步入的一个误区是按流程设计一个"理想的"组织架构,然后对应于这个架构对人员进行评估.培养,甚至是更换.我见过很 ...

  4. K:常见的正则表达式

    @装载自:http://zxin.cnblogs.com/ 平时对字符串进行校验和处理的时候难免会用到正则表达式,通常采用的方式是去网上寻找相关的正则表达式,之后copy下来进行修改,以使其满足自己的 ...

  5. NestedScrollingParent, NestedScrollingChild 详解

    之前听同事提起过 NestedScrollingView,但是一直没有时间去了解,最近一段时间比较空,才开始去了解.先点开,看 NestedScrollingView 源码: public class ...

  6. Yarn篇--搭建yran集群

    一.前述 有了上次hadoop集群的搭建,搭建yarn就简单多了.废话不多说,直接来 二.规划 三.配置如下 yarn-site.xml配置 <property>        <n ...

  7. Mac操作系统下忘记MYSQL的密码

    1. 在系统偏好 中,中止MySQL服务.: 2. cd/usr/local/mysql/bin   sudo ./mysqld_safe --skip-grant-tables 3. 登录MySQL ...

  8. python每日学习2018/1/11

    A.4 Python 关键字和内置函数 Python包含一系列关键字和内置函数,给变量命名时,知道这些关键字和内置函数很重要. 编程中面临的一个挑战是给变量指定合适的名称,变量名可以是任何东西,只要它 ...

  9. Mongo查询关键字

  10. Core Animation文档翻译 (第一篇)

    Core Animation 文档翻译(第一篇) 前言 作为iOS 开发,官方文档的阅读是很有必要的,值此周末便写下此文.作为iOS 实际经验3年的开发,之前有阅读并实践过经典的<iOS核心动画 ...