• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > C# Entity Framework中的IQueryable和IQueryProvider详解

C# Entity Framework中的IQueryable和IQueryProvider详解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了entity framework,entity framework教程,entity framework 6,entityframework.dll,entity framework 7等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

      相信大家对Entity Framework一定不陌生,我相信其中Linq To Sql是其最大的亮点之一,但是我们一直使用到现在却不曾明白内部是如何实现的,今天我们就简单的介绍IQueryable和IQueryProvider。

 IQueryable接口

      我们先聊聊这个接口,因为我们在使用EF中经常看到linq to sql语句的返回类型是IQueryable,我们可以看下这个接口的结构:

public interface IQueryable : IEnumerable
{
      Type ElementType { get; }
      Expression Expression { get; }
      IQueryProvider Provider { get; }
}
</div> 

      或许会有人很奇怪,当我们在开发过程中使用这个接口的时候,提供的方法远远不止这么点,因为微软提供了强大的Queryable类,当然大家不要以为这个类是实现IQueryable然后实现了很多方法,如果是那样那些第三方库怎么自定义呢?所以Queryable只是一个静态类,对IQueryable接口进行了扩展,下面是笔者在.Net Reflector截图中一部分:

       如果读者细心一点会发现linq to sql并不会导致实际的查询,只有当我们真正开始使用的时候才从数据库中开始查询数据。

IQueryProvider接口

      如果我们调试的EF的话,会看到生成的T-SQL语句。T-SQL就是根据表达式树分析从而得出的,而核心就是IQueryProvider接口,下面就是该接口的结构:

public interface IQueryProvider
{
        IQueryable CreateQuery(Expression expression);
        IQueryable<TElement> CreateQuery<TElement>(Expression expression);
        object Execute(Expression expression);
        TResult Execute<TResult>(Expression expression);
}
</div> 

      其中CreateQuery就是负责解析表达式树的,当然还要将处理后的结果返回,以便接着分析下面的语句,当然这中间只是分析,你完全可以根据表达式树得出你自己需要的查询语句,比如SQL或者其他什么,只有在真正使用数据的时候才会调用Execute方法,这个时候就可以根据我们自己分析的语句开始进行实际的查询了。

 实例分析

QueryProvider类

      光说不练我们永远不能明白其中的原理,所以下面我们就简单的举一个例子来展示下。首先我们先实现IQueryProvider接口,其中会用到一个Query类,这个类会在后面进行介绍,首先我们新建一个QueryProvider类实现IQueryProvider接口,首先我们看下CreateQuery<S>方法:

       这里的expression就是传递给我们,并且需要我们处理的表达式树,最后还要返回实现IQueryable<S>接口的示例,以便LINQ在此基础上进行下面的查询,这里我们仅仅只是创建了一个Query的实例,同时将expression传递给它,因为此处仅仅只是一个DEMO,所以我们没有去真正解析表达式树(这其中要做的工作很多)。接着还有CreateQuery方法:

 我们可以看到下面这句话:

实际的含义就是创建Query<>的实例,并且泛型参数是elementType,参数是this和expression。

 最后就是Execute方法了,传递一个Expression参数,并获取最后的结果,笔者在这里直接是写死的值:

 Query类

      仅仅只有QueryProvider还没用,我们还需要一个能够保存表达式树状态的类,当然也包括了我们解析表达式后的结果也可以保存在其中,这样我们在IQueryProvider的Execute方法中就可以根据我们解析的结果执行执行并返回结果了。

       这里我们可以看到Query的Expression值在创建这个实例时,如果没有传递Expression参数时该值就是:

       但是在后面的过程中Query中的Expression将是QueryProvider中的expression值。

       到此我们其实就完成了一个简单的示例了,我们就可以开始测试我们的成果了,笔者在利用如下的代码来测试:

      OK,我们开始看看是如何分析这句LINQ语句的。

       首先我们看下在一开始执行时Query中Expression的返回值(如下图):

      在获取到这个表达式后,就开始执行Linq,首先执行的是where item == 123。

 分析Where item == 123

     接着我们F5,就可以看到在QueryProvider中的CreateQuery<S>命中了,并且Expression参数如下图所示:

      我们看到里面的字符串是 Where(item => (item == 123)),通过这句话我们就可以明白其实LINQ中的where实质上就是利用Where方法,并传递给它对应的lambda表达式。分析完了where部分,下面就是FirstOrDefault部分了。

 分析FirstOrDefault

      当执行到FirstOrDefault的时候我们可以查看t的值,会发现t实际上就是QueryProvider中CreateQuery<S>的返回值。

 

      接着我们开始执行下面FirstOrDefault方法,发现会再一次的去获取Expression的值,而此时Expression的值就是上面CreateQuery<T>传递给我们的参数expression。

      然后在将这个表达式树和由表达式树表示FirstOrDefault方法调用的值拼接起来,并调用QueryProvider中的Execute<S>方法,我们可以看到这个时候传递给我们的参数expression的值。

       至此一个简单的流程就结束了,最后就是返回笔者写死的123这个值了。

       通过上面这个例子我们基本了解了其工作的流程,下面我们将一步一步的分析我们这个where item == 123,当然我们将会用到递归,所以请大家整理好自己的思路,一步一步的看如何从一个表达式树中分析这条语句。

 分析表达式树实战

      首先我们一个分析表达式树的方法,这个方法我们暂且放在QueryProvider中:

public void AnalysisExpression(Expression exp)
        {
            switch (exp.NodeType)
 &

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C# Entity Framework中的IQueryable和IQueryProvider详解

相关文章

  • 2017-05-28如何应用C#实现UDP的分包组包
  • 2017-05-28C#中图片.BYTE[]和base64string的转换方法
  • 2017-05-28自动输出类的字段值实用代码分享
  • 2017-05-28C#实现Ruby的负数索引器
  • 2017-05-28分享WCF文件传输实现方法---WCFFileTransfer
  • 2017-05-28C# listview 点击列头排序的实例
  • 2017-05-28c#中Linq to Sql 增删除的实例
  • 2017-05-28C#对文件/文件夹操作代码汇总
  • 2017-05-28关于C#基础知识回顾--反射(一)
  • 2017-05-28C# 设计模式系列教程-建造者模式

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C#实现实体类和XML相互转换
    • C#获取本机IP地址(ipv4)
    • C#学习基础概念二十五问 11-15
    • C#排序算法之快速排序
    • 深入c# GDI+简单绘图的具体操作步骤(二)
    • 全面解读C#编程中的析构函数用法
    • 深入解析:打造自动消失的对话框
    • C#常见算法面试题小结
    • C# 编码好习惯,献给所有热爱c#的同志
    • Repeater中添加按钮实现点击按钮获取某一行数据的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有