原文:LINQ TO SQL: OBJECTS ALL THE WAY DOWN
Author:Matt Warren
关于LINQ to SQL是什么或不是什么,目前有很多说法。其中有一些确实是基于某些人的调查研究,他们都亲手试过。作为它的构架师,我意识到我是最了解幕后原理的人,然而这并不能让我成为一个无所不知的神,使我能够知道这个产品是如满足每个人的期望的。我知道它做什么,因此我可以和你分享它的设计背后的动力和期望,相信你会从中得到启示,从而组建你自己的想法。
这对每个人来说这几乎不是什么秘密,一直以来,高位运行的LINQ to SQL都被称作LINQ;尽管仅仅在到底它会走多远这个问题上还不是很明显。LINQ to SQL不是另外一个LINQ供应者。设计LINQ的过程,从一开始并且现在仍然是在塑造它和背其塑造,使其成为一个精髓的LINQ提供者。因此要了解LINQ to SQL背后的动力,你需要了解LINQ背后的动力。
LINQ不仅仅是简单的将查询语法添加到现在的编程语言中。LINQ是一种认识,那就是对象(在我们的案例中指的是CLR对象)是你们作为程序员要做的每一件事的核心内容。在过去,你们会有多种控制和转换数据库的规则和其它脚本。然而你们的所有工作的中心却是围绕主流编程语言和运行时库做的其它事情,你们不是用对象来很自然的展现各种各样的编码工作而是用很粗糙的API,你们没有用开发工具支持的语言内建的各种构造,而是将特定领域的语言(例如sql)作为不可识别的文本契入到系统中。虽然这些API能够胜任但却不理想。你们虽然将事情做完了,但是这就像通过钥匙孔来翻找数据,当一些数据通过它反吸回去时,它基本上已经坏掉了,因为处理数据的工具中没有一个可以为你跨越这种分割来向前推进。相信我说的,因为我就写过很多类似的API。
因此对于高位运行的LINQ来说,不仅有可能让你将领域数据通过对象展现出来,而且还能够以一流的具体领域方式来操作各种对象。 LINQ对SQL的转换是一个贴海报的小孩。在操作的区域中,查询是其中的重要一块。既然查询在绝大部分的其它频繁使用的领域中蔓延,这是一个明显的趋势,在语言和运行时库中,查询应该变成最佳趋势。 LINQ对SQL转的的主要工作变成了将关系数据库中的数据以对象的形式展现出来和将查询一体化语言转成远程执行的数据库查询。
当然,既然LINQ转SQL与ORM系统的功能范围恰好重叠,因此它也扮演了ORM的角色也不足为奇,它们都在语言中使用的各种对象与关系数据库中数据的形态之间实现了映射。我们从老练的客户那里获取了那些系统的最有价值的特性,并且还为发布那些特性制定了线路图,然而就像随着提交产品这一事实最后逐渐临近,各种优先级也相应而生。但不幸的是,有很多我们都很喜欢做的事情在切断版本时并没有被包含在第一个版本中。但是这不是遗憾。LINQ转SQL已经聚集了一堆会带来一大块市场的特性,并且随着时间的推移,它只会变得更好。
对于了解LINQ转SQL,真正有趣的事情是它到底有多深。
从一开始,我们的主要宗旨是实现原始对象开发(POCO)。从我们收到的足够多的早期ObjectSpaces原型反馈中得知,我们的用户很在意POCO开发和那些具体与他们关系紧密的事情。然而,当我们找到了提供诸如EntityRef和EntitySet专门类的理由时,我们从来都没有迷失方向,因为这些专门类的使用总是可选的。你当然可以用原始的对象引用和诸如list和array的集合来编写对象,你只是没有用延期加载或者双向指针安排。并且尽管一些人令可我们发明一个廉价的拦截方案,在这个方案中,你应该允许这些行为而不需要使用专门类,但是那些方案始终都没有出现。这些类型的使用可以很容易地在各种属性背后假装。
同样有必要指出的是这些专门类的使用实际上不会使你将数据访问逻辑和业务对向混淆在一起。EntityRef和EntitySet不会反过去和数据库或LINQ转SQL构架绑在一起。它们的设计使它们完全摆脱了那些累赘的束缚,没有任何对各种上下文,连接或者是其它抽象事物的反向引用。延期加载基于给它们都赋值一个简单的,诸如一个LINQ查询的IEnumerable数据源。那就是它。你可以随意地重用它们,不管是出于什么样的目的。
但是,事情到那里还没有结束。各种对象的使用和CLR都在LINQ转SQL的设计中蔓延。你可以发现对Insert,Update和Delete行为的从载被允许。这个方案不是提供一个基于映射的方案来将这些提交行为和数据库存储过程连接起来,而是利用各种对象和运行时,以及通过定义一个方法将代码添加到系统中的能力。你可以定义一个InsertCustomer方法作为你的DataConext的一部分,然后LINQ转SQL运行时调用它。这使你可以重载一个insert的执行。在这个方法中,你可以写日志,跟踪和执行你想的sql或者是根本没有sql的任何事情。当然,当你用设计器将一个提交的行为和一个存储过程连接起来时,所有的这一切都已经为你接通。但是它的美妙之处在于使用运行时和语言基本扩展机制来实现你需要的自定义方案的简易性。
你会发现可以通过使用CLR自定义属性来定义映射。当然了,同样可以通过一个额外的映射文件来提供不同的实现,但是属性模型是极其重要的。有人会反驳道,在代码中使用属性会破坏纯粹的POCO设计。这种说法可能是正确的。然而,确切地说这使得你的各种对象的定义内联映射起来,使LINQ转SQL简单和易于启动,因为你可以保持关注你的各种对象和代码。
你同样可以看见LINQ转SQL的内部工作原理,或者它们是如何与provider通信的。各种查询是LINQ表达式树,这种表达式树贯穿了到转换管道的整个过程。它们是你定义的各种对象类型和运行时元数据,你可以直接分辨它们,对它们进行创建,比较和控制操作。它们是合理的,被创建,比较和驾驶的对象和运行时元数据。就连对存储过程的调用都被理解为对DataContext上定义的方法签名的引用,至于各种查询临时的返回结果不是像DataReader那样具有笨拙访问器的一般对象,而始终是你自己定义的对象或者是通过匿名类型创建器定义的对象,通过强类型字段或者属性相互作用。
让我们回顾一下,有很多东西只是现在看起来很明朗,但是相信我,就在我们开始这个项目的那一刻,没有一件事情已经就绪。例如,在我们设计ObjectSpaces时,就没有考虑到这些内容。在LINQ之前,这些内容中的大部分甚至都没有被考虑。然而,当LINQ转SQL的那一刻来临时,我们在设计上采用了折衷的办法。我们使用运行时和语言的内建机制来操作各种对象以及保持其简单的特性。
当数据库访问和面向对象语言搅拌在一起时,LINQ帮助我们解决了这个难题。LINQ转SQL成了对象到数据库解决方案的化生,它使你将设计的焦点保持在查询,领域对象以及语言和运行时的整合上。
当然,这里还有其它的设计目标,简单明了,易于使用和性能都是一些关注点同样有必要一一介绍。我想我会把他们都写出来的。

本文由LINQ to SQL的构架师Matt Warren撰写,深入探讨了LINQ to SQL的设计理念及其如何实现原始对象开发的目标。文章解释了LINQ to SQL如何通过对象展现数据库数据并执行数据库查询,同时保持数据访问逻辑与业务对象分离。
883

被折叠的 条评论
为什么被折叠?



