Log4X

链路纵横
Linq将何去何从
微软的EntityFramework随着.net Framework 3.5sp1一起发布了,这个Entity Framework 虽然与linq to sql同为orm框架,但绝非linq to sql的升级。
EntityFramework的风格更像ado.net的标准写法,查询语句并非linq风格,而是普通的字符串。这好像与 Hibernate的HQL又走到了一起。
在我看来,EntityFramework 的推出基本上就意味着linq to sql退出历史舞台。而Linq 就如高楼还未建成,就缺了最主要的那根顶梁柱,难有完工那一天了。
Linq是.net Framework 3.5力推的编程特性,号称将改变程序员的编程习惯的东西,在之前推出的一系列如扩展方法,var类型,都是为linq打基础。但是现在不得不说,Linq还没来得及风光,好日子恐怕就要过去了。
Entity Framework为何不再linq to sql基础上发展,而采用ado.net的传统风格?我想主要还是Linq自身的一些缺陷。
首先linq的风格虽然华丽,但是写法和其他代码格格不入,影响整体布局。
其次linq的写法不能支持动态附加的查询条件(要加条件只能直接使用Where()这样的扩展方法)。linq的查询语句,翻译成扩展方法,就是方法链的风格,而你无法在不使方法链中断的情况下,动态的指定到底执行链中的哪些方法。而如果采用字符串作为查询语句,那么就灵活多了——你可以随意的拼凑字符串,直至最终得到你所需的。
最后一个问题,也是linq最大的硬伤:linq查询语句本身就是程序执行的一部分。就因为这,使得在程序运行时还没来得及对整条语句进行分析,就已经不得不开始执行一些子句了。select子句必须写在最后就是这个问题的最直接证明。当然这个问题的影响远远不止select子句的位置那么简单。因为运行时无法对linq语句有个整体的分析,因此这个工作不得不被放到了编译期,但是编译期所能获得的信息与运行时不可同日而语,光是最重要的一点:实际数据库的情况,在编译时,编译器对它就一无所知。
就因为这个原因,很多复杂的查询功能,linq不是实现不了,就是实现起来很复杂,并且大部分情况都得在linq语句的这里那里嵌满扩展方法,反而不优雅。又比如更新,就会先查询再更新;删除会一条条删除,不会直接批量删除。

再拿最简单的外连接抓取(orm框架并不常需要显式作连接查询,但由于lazy-loading产生的n+1问题,外连接抓取是一种提高性能的方案)来说,在linq中就必须用 join ...into形式的句式将结果选入一个临时变量,然后再另开一个from子句将临时变量中结果选出,如

var res = from p in ctx.Products
                       join c 
in ctx.Categories
                       on p.CategoryID equals c.CategoryID
                       into pro
                       from x 
in pro.DefaultIfEmpty()
                       select p.ProductName;

 

复杂程度甚至还远远超过sql的外连接查询。

而如果采用字符串作为查询语句,那么在运行时对查询语句进行解析就变得轻而易举,查询语句能力理论上也就可以和sql做得一样强大。

因此我认为,最后所提的这个问题就是导致Entity Framework舍弃linq风格,回归字符串的主要原因。

从概念上讲,Entity Framework虽然后于linq to sql出来,但是linq to sql更有未来感,很前卫很激进。但微软走这条路显然不顺利,无论前面为它做了多少准备,多少铺垫,到最后发现还是走不下去。而Entity Framework则是一种理性的回归,更务实更保守,它的这条路,Hibernate早在几年前已经走通了,所以技术上不会有任何问题。

posted on 2008-08-16 00:13  YYX  阅读(869)  评论(3编辑  收藏  举报