而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

时间:2022-05-14 07:14:33

相信大家对

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; }

}

或许会有人很奇怪,当我们在开发过程中使用这个接口的时候,供给的要领远远不止这么点,因为微软供给了强大的

Queryable

类,固然大家不要以为这个类是实现IQueryable然后实现了很多要领,如果是那样那些第三方库怎么自界说呢?所以Queryable只是一个静态类,对IQueryable接口进行了扩展,下面是笔者在


.Net Reflector


截图中一部分:

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

如果读者细心一点会发明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);

}

此中

CreateQuery

就是卖力解析表达式树的,固然还要将措置惩罚惩罚后的功效返回,以便接着分析下面的语句,固然这中间只是分析,你完全可以按照表达式树得出你本身需要的盘问语句,好比SQL或者其他什么,只有在真正使用数据的时候才会挪用

Execute

要领,这个时候就可以按照我们本身分析的语句开始进行实际的盘问了。


实例分析


QueryProvider类

光说不练我们永远不能大白此中的道理,所以下面我们就简单的举一个例子来展示下。首先我们先实现IQueryProvider接口,此中会用到一个Query类,这个类会在后面进行介绍,首先我们新建一个

QueryProvider

类实现IQueryProvider接口,首先我们看下

CreateQuery<S>

要领:

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

这里的

expression

就是通报给我们,并且需要我们措置惩罚惩罚的表达式树,最后还要返回实现IQueryable<S>接口的示例,以便LINQ在此根本长进行下面的盘问,这里我们仅仅只是创建了一个Query的实例,同时将expression通报给它,因为此处仅仅只是一个DEMO,所以我们没有去真正解析表达式树

(这此中要做的事情很多)

。接着还有CreateQuery要领:

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

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

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

实际的含义就是创建

Query<>

的实例,并且泛型参数是

elementType

,参数是

this



expression

最后就是

Execute

要领了,通报一个

Expression

参数,并获取最后的功效,笔者在这里直接是写死的值:

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression


Query类

仅仅只有

QueryProvider

还没用,我们还需要一个能够生存表达式树状态的类,固然也包孕了我们解析表达式后的功效也可以生存在此中,这样我们在IQueryProvider的Execute要领中就可以按照我们解析的功效执行执行并返回功效了。

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

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

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

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

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

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

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

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

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

而此时Expression的值就是上面 CreateQueryT 传递给我们的参数 expression

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


分析Where item == 123