代码改变世界

LINQ and Pipeline Pattern

2008-08-06 00:06  Jun1st  阅读(1736)  评论(13编辑  收藏  举报

INTRODUCTION

LINQ: Language-Integrated Query是随着.NET 3.5而来的extension。这里不多做介绍了,有兴趣的可以看这里YJingLee有一系列不错的文章,值得一看。

在软件工程中,Pipeline是指有一系列元素组成的一条链,上一个元素的输出是下一个元素的输入。Pipeline Design Pattern也被称作为Pipes and Filters Design Pattern。本文将介绍利用LINQ和C# 3.0的新特性来实现Pipeline 模式

Pipeline

 

MAIN

切入正题:假设我有一个GetPosts()方法,获取博客园中所有的Post。我们利用LINQ来实现数据库操作,PostDataContext。因此,在GetPosts这个方法中的代码如下:

Code1

此方法返回的是将是所有的Post,我们可以把这个posts比作为“Raw Data”。由于LINQ的deferred querying的特性,此方法在第一次被调用时,并不会立即执行此取数据的操作,在debug的时候可以看到posts其实是一组SQL语句。在当返回的posts在被Enumerate时,才会真正执行这个SQL语句。我们可以利用这一特性和C# 3.0的extension method来实现Pipeline模式。

写一个Extension method

Code2

用此Extension method就可实现filter的功能

Code3

此IQueryable<Post>就是由Raw Data过滤之后得到的Data 1。由于Deferred Querying, GetPostsByAuthor并不会先从数据库取得所有的数据,再在内存中通过Author来过滤,而是会在数据库中执行有Author过滤条件的SQL语句。

有一点需要注意,在整个Pipeline的中间流程当中,返回的结果需要是IQueryable<T>的,如果返回的是IList<T>, IList<T>来自IQueryable<T>.ToList(), 此ToList方法将会使LINQ执行,此后的操作将会是在内存中执行。

CONCLUSION

.NET 3.0的extension method使得Pipeline Pattern的实现显得更加的自然。LINQ的特性使得这一模式有更高的效率,因为Raw Data并不需要取回数据保存在内存中。当然,执行一个SQL取回的大量的数据保存在内存中以备后用,和分散的多次执行SQL始终是一个需要平衡的的事情。