一直没去细想为什么Enumerable和Queryable提供了两套签名一致的方法.今天在扩展IQToolkit,使之支持Insert/Update/Delete的过程中,遇到了问题,用Reflector看了一下Queryable类的源码,顿时醍醐灌顶.

在给代表数据库表格的类EntityTable(实现了IQueryable<TEntity>接口)添加一个扩展方法Delete(Expression<Predicate<TEntity>>)来做生成Delete语句的标识时,发现这个方法被直接调用了,觉得很郁闷.明明微软自己的Where, Select等方法都没被调用,而是作为Expression给传到了QueryProvider里, 凭什么我自己写的方法你就不给翻译一下传过去,而是当场执行呢?

不对啊,First, Single之类的方法也是当场执行的啊,难道编译器会根据方法的返回类型(是不是相同的IQueryable<T>)来决定如何对待它们?或者,可能有某个应用于方法上的Attribute,可以控制编译器这方面的行为?

还是看看Queryable里的代码是怎么写的吧.打开Reflector一看Queryable.First方法,马上明白了:

public static TSource First<TSource>(this IQueryable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    return source.Provider.Execute<TSource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression }));
}

晕了,原来根本不是编译器在捣鬼!这方法纯粹是一混蛋,屁事不干的主.不单屁事不干,还指使别人说,你再来调用我吧..

再看Queryable.Where:

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    return source.Provider.CreateQuery<TSource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression, Expression.Quote(predicate) }));
}

First和Where的区别在于两者调用了不同的方法,一个要求直接执行对应的动作,一个要求返回一个新的IQueryable<T>对象以推迟实际行为的发生.

哎,这世界上怎么那么多比我聪明的人呢?

原来Queryable是这样实现的..相关推荐

  1. MongoDB 开源“可查询加密”系统 Queryable Encryption

    整理 | 彭慧中 责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 多年来,数据泄露与黑客攻击令人苦不堪言.全世界都急于寻找一种工具来阻止个人敏感数据的非法流动,然而一个关键性的进展已经初 ...

  2. Linq中的Enumerable和Queryable

    前言 正文 使用场合不同 返回类型不同 传递参数不同 总结 前言 此文章延续自C#中Linq的使用 正文 上节讲到Linq可以通过查询方法来使用,Linq中有两个命名空间,分别是System.Linq ...

  3. 开源:ASP.NET MVC+EF6+Bootstrap开发框架

    前言 我在博客园潜水两三年了,在这里看过很多大神的文章,也学到了很多东西.可以说我是汲取着博客园的营养成长的. 想当年,我也是拿10个G的精神粮食从一个博客园大神那里换来一套开发框架,正式走上开发之路 ...

  4. MVC+Ninject+三层架构+代码生成 -- 总结(四、數據層)

    1.數據層使用了SqlSugar 庫類 . 數據層使用了SqlSugar 庫類 ,有興趣的 可以學習  http://www.codeisbug.com/Doc/8/1133,個人覺得比EF 簡單,容 ...

  5. graphql_普通英语GraphQL指南

    graphql by Luis Aguilar 路易斯·阿吉拉尔(Luis Aguilar) 普通英语GraphQL指南 (A Guide to GraphQL in Plain English) 您 ...

  6. 耗时3天,上亿数据如何做到秒级查询?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:sohu.gg/jIp59N 最近在忙着优化集团公司的一个报 ...

  7. 教你如何实现c#文件上传下载功能

    简单介绍一下c#文件上传下载功能实现. NuGet 安装SqlSugar Model文件下新建 DbContext 类 public class DbContext {public DbContext ...

  8. java 拉姆表达式_强大的拉姆表达式转Sql 类库 - SqlSugar 隐藏功能之Lambda

    使用场景 1.Lambda to sql 一直是ORM中最难的功能之一,如果有现成的解析库那么自已写一个ORM难度将大大降低 2.通过Lambda作为KEY进行缓存操作,特别是仓储模式想要拿到表达式进 ...

  9. mysql java orm_ObjectiveSQL(Java ORM) 之 MySQL 实战

    第一步,引用Maven依赖: com.github.braisdom objective-sql 1.3.4 第二步,使用Annotation 定义一个DomainModel : import com ...

最新文章

  1. 精准广告系统架构调研
  2. 周志华:“数据、算法、算力”,人工智能三要素在未来还要加上“知识”
  3. python降级-关于卸载:如何从Python 3.2降级到2.7?
  4. 20165214 预备作业3 Linux安装及学习
  5. 华为鸿蒙宣传悟空视频_给华为“鸿蒙”打Call,家居头条号探讨短片《悟空》获50万阅读...
  6. php 伪造微信浏览器头信息,php使用curl伪造浏览器访问操作示例
  7. C++_limits头文件
  8. Java基于SSM的宠物店管理系统
  9. react中使用video标签显示本地视频不生效问题
  10. 谷歌浏览器安装 elasticsearch-head 插件
  11. Beyond Compare4破解方法
  12. 程序员编程规范之注释
  13. 连连跨境支付独立站收款,最高90天提现0费率!
  14. 二手平台android界面,Android二手书交易app设计(2)启动图Activity
  15. [重要笔记]路由器的包转发操作(全面认识路由器)
  16. 思科三层交换机开启ipv6路由功能_思科路由器配置 IPv6 和 OSPFv3 路由
  17. 机器学习笔记马尔可夫链蒙特卡洛方法(二)马尔可夫链与平稳分布
  18. 各种文件对应的文件类型
  19. 云数据库 Redis 版
  20. java做全选反选功能_[Java教程]js实现全选反选

热门文章

  1. c++调用python找不到py文件的可能原因
  2. 我心中的核心组件(可插拔的AOP)~第十五回 我的日志组件Logger.Core(策略,模版方法,工厂,单例等模式的使用)...
  3. Apache Storm源码阅读笔记
  4. [一文一命令]ln命令详解
  5. 设计模式 (一) 初次体验
  6. 深度剖析WinPcap之(二)——网络分析与嗅探的基础知识(4)
  7. 【译】TetroGL: An OpenGL Game Tutorial in C++ for Win32 Platforms - Part 2 (上)
  8. ZooKeeper 特点有哪些?
  9. 浅谈长连接的平滑重启
  10. 天猫精灵 python_python爬天猫