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语句的这里那里嵌满扩展方法,反而不优雅。又比如更新,就会先查询再更新;删除会一条条删除,不会直接批量删除。
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;
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早在几年前已经走通了,所以技术上不会有任何问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端