认识IQueryable和IQueryProvider接口
1.Func<Student, bool>和Expression<Func<Student, bool>>的区别
class Program
{
static void Main(string[] args)
{
Func<Student, bool> func = t => t.Name == "";
//匿名函数
Expression<Func<Student, bool>> expression = t => t.Name == "";
//表达式树 有Body Right、Left,Right里面又有Right、Left,它们的类型都是继承自 Expression 。这种节点下面有节点,可以无限附加下去的数据结构我们称为树结构数据。也就是我们的表达式树。
Console.Read();
}
} public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string Sex { get; set; }
}
2.解析表达式树
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; namespace RedisTest
{
class Program
{
static void Main(string[] args)
{
Expression<Func<Student, bool>> expression = t => t.Name == "" && t.Name == "";
AnalysisExpression.VisitExpression(expression);
/*
运算符:AndAlso
运算符:Equal
字段名称:Name,类型:System.String
常量值:1111
运算符:Equal
字段名称:Name,类型:System.String
常量值:2222
*/
Console.Read();
}
} public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string Sex { get; set; }
} public static class AnalysisExpression
{
public static void VisitExpression(Expression expression)
{
switch (expression.NodeType)
{
case ExpressionType.Call://执行方法
MethodCallExpression method = expression as MethodCallExpression;
Console.WriteLine("方法名:" + method.Method.Name);
for (int i = ; i < method.Arguments.Count; i++)
VisitExpression(method.Arguments[i]);
break;
case ExpressionType.Lambda://lambda表达式
LambdaExpression lambda = expression as LambdaExpression;
VisitExpression(lambda.Body);
break;
case ExpressionType.Equal://相等比较
case ExpressionType.AndAlso://and条件运算
BinaryExpression binary = expression as BinaryExpression;
Console.WriteLine("运算符:" + expression.NodeType.ToString());
VisitExpression(binary.Left);
VisitExpression(binary.Right);
break;
case ExpressionType.Constant://常量值
ConstantExpression constant = expression as ConstantExpression;
Console.WriteLine("常量值:" + constant.Value.ToString());
break;
case ExpressionType.MemberAccess:
MemberExpression Member = expression as MemberExpression;
Console.WriteLine("字段名称:{0},类型:{1}", Member.Member.Name, Member.Type.ToString());
break;
default:
Console.Write("UnKnow");
break;
}
} }
}
3.认识IQueryable和IQueryProvider接口
ElementType 代表当然这个Query所对应的类型
Expression 包含了我们当然Query所执行的所有查询或者是其它的操作
IQueryProvider则是负责处理上面的Expression的实现
IQueryProvider只有两个操作,CreateQuery和Execute分别有泛型版本和非泛型版本。 CreatQuery用于构造一个IQueryable<T>的对象,这个类其实没有任何实现,只是继承了IQueryable和IEnumrable接口。主要用于计算指定表达式目录树所表示的查询,返回的结果是一个可枚举的类型。 而Execute会执行指定表达式目录树所表示的查询,返回指定的结果。
4.实现自己的IQueryable<T>、IQueryProvider
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; namespace RedisTest
{
class Program
{
static void Main(string[] args)
{
var aa = new MyQueryable<Student>();
var bb = aa.Where(t => t.Name == "");
var cc = bb.Where(t => t.Sex == "男");
var dd = cc.AsEnumerable();
var ee = cc.ToList();
//每次在执行 Where 查询操作符的时候都会把lambda转化为express存放在MyQueryable的Expression里
//调用 AsEnumerable() 方法的时候并不会去实际取值(只是得到一个IEnumerable)[注意:在EF里面查询不要先取IEnumerable后滤筛,因为AsEnumerable()会生成查询全表的sql]
//执行 ToList() 方法时才去真正调用迭代器 GetEnumerator() 取值
//真正取值的时候,会去执行 IQueryProvider 中的 Execute 方法。(就是在调用这个方法的时候解析表达式数,然后执行取得结果)
//我们看到真正应该办实事的 Execute 我们却让他返回默认值了。
}
} public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string Sex { get; set; }
} public class MyQueryProvider : IQueryProvider
{
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new MyQueryable<TElement>(expression);
} public IQueryable CreateQuery(Expression expression)
{
throw new NotImplementedException();
} public TResult Execute<TResult>(Expression expression)
{
return default(TResult);
} public object Execute(Expression expression)
{
return new List<object>();
}
}
public class MyQueryable<T> : IQueryable<T>
{
public MyQueryable()
{
_provider = new MyQueryProvider();
_expression = Expression.Constant(this);
} public MyQueryable(Expression expression)
{
_provider = new MyQueryProvider();
_expression = expression;
}
public Type ElementType
{
get { return typeof(T); }
} private Expression _expression;
public Expression Expression
{
get { return _expression; }
} private IQueryProvider _provider;
public IQueryProvider Provider
{
get { return _provider; }
} public IEnumerator GetEnumerator()
{
return (Provider.Execute(Expression) as IEnumerable).GetEnumerator();
} IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
var result = _provider.Execute<List<T>>(_expression);
if (result == null)
yield break;
foreach (var item in result)
{
yield return item;
}
}
}
}
再一个例子
class Program
{
static void Main(string[] args)
{
var DB = new wolf_testEntities();
decimal aa = ;
ParameterExpression pExpression = Expression.Parameter(typeof(People));
var getPropertyValue = Expression.Property(pExpression, typeof(People).GetProperty("Num"));
ConstantExpression cExpression = Expression.Constant(aa);
BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.GreaterThan, getPropertyValue, cExpression);
Expression<Func<People, bool>> lambda = Expression.Lambda<Func<People, bool>>(bExpression, pExpression);
//Expression Tree 的条件 x=>x.Num>0
var bbb = DB.People.Where(lambda).ToList();
Console.ReadLine();
}
}
认识IQueryable和IQueryProvider接口的更多相关文章
- IQueryable和IQueryProvider初尝
前言 相信大家对Entity Framework一定不陌生,我相信其中Linq To Sql是其最大的亮点之一,但是我们一直使用到现在却不曾明白内部是如何实现的,今天我们就简单的介绍IQueryabl ...
- IQueryable 与 IEnumberable 接口的区别
IQueryable 与 IEnumberable 接口的区别是: IEnumberable<T> 泛型类在调用自己的 SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了, ...
- .NET架构设计、框架设计系列文章总结
从事.NET开发到现在已经有七个年头了.慢慢的可能会很少写.NET文章了.不知不觉竟然走了这么多年,热爱.NET热爱c#.突然想对这一路的经历进行一个总结. 是时候开始下一阶段的旅途,希望这些文章可以 ...
- .NET系列文章——近一年文章分类整理,方便各位博友们查询学习
由于博主今后一段时间可能会很忙(准备出书:<.NET框架设计—模式.配置.工具>,外加换了新工作),所以博客会很少更新: 在最近一年左右时间里,博主各种.NET技术类型的文章都写过,根据博 ...
- NET系列文章
NET系列文章 由于博主今后一段时间可能会很忙(准备出书:<.NET框架设计—模式.配置.工具>,外加换了新工作),所以博客会很少更新: 在最近一年左右时间里,博主各种.NET技术类型的文 ...
- .NET深入解析LINQ框架2
1].开篇介绍 在开始看本篇文章之前先允许我打断一下各位的兴致.其实这篇文章本来是没有打算加“开篇介绍”这一小节的,后来想想还是有必要反馈一下读者的意见.经过前三篇文章的详细讲解,我们基本上对LINQ ...
- 再讲IQueryable<T>,揭开表达式树的神秘面纱
接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...
- 不可不知的表达式树(3)定制IQueryProvider
前面我们说到利用表达式树技术实现LINQ-to-SQL,实际上可以针对任何数据源,实现LINQ-to-Everything.这里还涉及到两个重要的接口即IQueryable和IQueryProvide ...
- 【转】再讲IQueryable<T>,揭开表达式树的神秘面纱
[转]再讲IQueryable<T>,揭开表达式树的神秘面纱 接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个 ...
随机推荐
- eMMC基础技术7:Bus Speed Modes
1. 前言 eMMC有多种速率模式,主要根据如下几个方面进行划分: single rate or dual rate I/O电压 BUS宽度 支持的clock频率范围 最大的传输速率 2. 概览 图 ...
- mongoDB Liunx下安装及配置
以下以ubuntu 16.04(64位)操作系统为例: 一.下载和安装 在ubuntu下安装mongodb可以使用 apt-get进行安装,也可以直接下载编译好的二进制文件进行安装.下面主要介绍使用二 ...
- PEP525--异步生成器
[译] PEP 525--异步生成器 PEP原文:https://github.com/python/peps/blob/master/pep-0525.txt 创建日期:2016-07-18 译者 ...
- 用WMI监控IIS
参考网站:http://blog.chinaunix.net/uid-7910284-id-5774420.html 参考官方文档:https://docs.microsoft.com/en-us/p ...
- windows下django1.7 +python3.4.2搭建记录1
python+django在linux下搭建比较简单,windows下搭建比较复杂,所以列在下方一.下载安装下载django的包,到刚解压后的Django-1.7目录下执行命令 python setu ...
- 题解-CodeForces835F Roads in the Kingdom
Problem CodeForces-835F 题意:求基环树删去环上任意一边后直径最小值,直径定义为所有点对最近距离的最大值 Solution 首先明确删去环上一点是不会影响树内直径的,所以应当先把 ...
- Mac下更改JDK环境变量配置
1.打开终端 2.如果你是第一次配置环境变量,可以使用“touch .bash_profile” 创建一个.bash_profile的隐藏配置文件(如果你是为编辑已存在的配置文件,则使用"o ...
- 缓存系列之三:redis安装及基本数据类型命令使用
一:Redis是一个开源的key-value存储系统.与Memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括:字符串.哈希表.链表.集合.有序集合以及基于这些数据类型的相关操 ...
- JMeter 中_time 函数的使用(时间戳、当前时间)
有时在接口测试时,其参数需要为时间戳或者是日期格式的数据.针对此问题,可以使用JMeter自带的_time 函数来解决以上问题 操作步骤: 1.通过函数助手,生成一个_time 函数: 2.如果参数为 ...
- Eleaticsearch源码分析(一)编译启动
转自:https://lunatictwo.github.io/2017/12/21/Eleaticsearch%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90(%E4%B8% ...