inqToDB框架最大的优势应该是实现了对Linq的支持。如果少了这一个功能相信他在使用上的快感会少了一个层次。本来笔者想要直接讲解LinqToDB框架是如何实现对Linq的支持。写到一半的时候却发现本系列在内容上的引导显得格外的生硬。思考在三最后还是决定在讲解LinqToDB框架之前来一章过度文。

Linq查询的原理


我们在学习Linq的时候会见到一些很常见的关键词语。比如Linq To SQL、Linq To Objects、Linq To XML等。事实这些一般都是根据不同的数据源来进行命名的。 说实话笔者当初学习的时候,看到这些命名险些以为只有这几种。事实不是这样子的。Linq有俩个核心类——Enumerable类和Queryable类。这俩个类可以说贯穿整个Linq知识体系。如果有心的朋友可以点开对应的dll包就是发现他们都在System.Linq命名空间下。同时他们都是用于扩展相应的静态方法。而且方法名大至相同。然后他们却在本质上有着细微的差别。Enumerable类是对IEnumerable<T>接口进行扩展并且传入了Func类型的参数。数据源是来自于内存中的。而Queryable类是对IQueryable<T>接口进行扩展,传入参数是表达式(Expression类型)。数据源是来自于第三方。比如SQL Server、MySql等。

Linq的思想就是提供一个统一模型操作来处理数据。所以本质来讲对数据源不是很讲究。比如数据源是文件,或则说数据源是Excel之类的。相信可能有人已经看到过Linq To Excel呢?主要辛苦还是这些开发底层的人。对于使用者来讲没有什么多大的差别。Linq现在面对数据源而扩展功能有很多。其中专对数据库来讲,最流行还是有Linq To SQL。而且扩展数据库的Linq功能大多数都用IQueryable<T>接口。当然,这不是说用IEnumerable<T>接口就不行了。只是这俩种接口在实现上有着很大的差别。IEnumerable<T>接口我们都知道他一般是专对于内存的。这意味着我们必须把相应的数据全部加载到内存中才可以进行查询。这样子的操作太伤性能了。而IQueryable<T>接口我们可以巧妙的用上表达式树(Expression Tree)进行转化生成对应的数据库SQL语句,然后在执行数据库。这才是显得合理。

ORM思想能流行大体上可以说是因为他的思想更加贴切于人类的思维方式。在笔者看来如果把Linq技术说成也是ORM思想的产物之一,这样子的说法也不为过。这也是笔者喜欢Linq的地方。LinqToDB框架只所以都能支持Linq。不可否认也是依据这一种上面所讲的原理来实现的。大体的想法如下。

  1. 实现Linq提供的IQueryable<T>接口和IQueryProvider接口。生成相关的表达式树。

  2. 把对应的表达式树转化生成对应数据库的SQL语句。并执行。

  3. 根据映射的信息,生成对应的集合类。(这里的集合类是指SQL语句执行结果转成类放入的集合)

实现自定义的Linq查询一定离不开俩类——IQueryable<T>接口和IQueryProvider接口。上面的工作可以说都在这俩类上面。IQueryable<T>接口一般用于生成对应的表达式树。而IQueryProvider接口用于执行表达式树,转化成对应的SQL语句,执行数据库并生成映射的模型对象。

注意:IQueryable<T>接口是什么样子生成相关的表达式树呢?让笔者来讲的话,笔者觉得有一点浪费时间。但是不要当心博客园里面有一位大神写的博文一定能满足你——王清培的《.NET深入解析LINQ框架》

实现Linq查询


支持Linq查询本意上就是实现上面所讲的俩个接口。当你实现IQuer