Blog信息 |
blog名称:注册会计师(注会)练习软件 日志总数:398 评论数量:116 留言数量:27 访问次数:3270098 建立时间:2005年6月6日 |

| |
[borland eco 技术]转贴:对象化查询之OCL vs. OPath 软件技术
吕向阳 发表于 2006/6/11 14:27:17 |
对象化查询之OCL vs. OPath
令人心动的对象化查询
对象化查询是O/R Mapping中非常让人心动的一个特性,当所有的表对我们来说不复存在后,我们可以对实体进行CRUD,可是当我们需要返回多个实体的结果集时,我们怎么办呢?Dataset做为载体是必然的,可是我们查询过滤数据的方式是怎样的?sql?No!我们就是在尽量避免直接使用sql,因为sql不便于重构,可移植性太差,拼凑出来的sql语句对测试覆盖率也有影响。所以大家都期待着可以用对象化查询来根除将Entity再当做Table来处理的尴尬。
.Net下的O/R Mapper对对象化查询的支持
目前为止,.Net下的O/R Mapper对对象化查询的支持绝大部分都是非常有限的:NHibernate用的是HQL语句,其本质可以说是一种把Entity看做Table的改装后的sql语句,DataObjects.Net和NHibernate差不多,也有一套自己的类sql对象化查询语法,其它很多O/R Mapper使用的是简单的属性过滤查询,而说到对对象化查询支持得最强大的,要算ECOⅡ和ObjectSpaces,前者使用的是OCL语法,后者是OPath。
OCL起源
OCL是OMG组织制订的UML语言规范的一部分,它的初衷是用来对UML模型视图中的Object添加约束描述的,并不是一种编程语言,而OCL应用到O/R Mapping中就俨然成了一种对对象进行查询的语言(OQL)。
OPath起源
OPath是MS提出的在WinFS中准备大量使用的一种对象查询语言,从它的命名上可以看出和XPath的相似之处,MS的口号一直是把复杂的东西变简单,把简单的东西变成自动化。所以这个OPath确实不可小觑。
简单的例子
先我们从一个简单的例子入手,假设有如下的实体关系(画图太麻烦,还浪费空间):
Department (code name employees)
Employee(code name department salary)
查询
OCL
OPath
包含薪水大于3000的员工所有部门
Department.allInstances->select(self.employees.includes(salary > 3000))
Exists(employees[saleary > 3000])
得到部门001的所有员工
Employee.allInstances->select(self.department.code = ‘001’)
Department.code = ‘001’
所有员工薪水都大于3000的部门
Department.allInstances->select(self.employees.forAll(salary > 3000))
不支持
员工最高薪水大于3000的部门
Department.allInstances->select(self.employees.includes(salary > 3000))
不支持
功能比较
从这个列表中可以看到OPath的语法要简洁得多,但OCL的集合操纵能力却是OPath无法比拟的,下面是OCL的一些集合函数:
名称
功能
Collect
得到一个属性的集合
Exists
如果存在符合条件的元素为真
forAll
只有所有集合元素符合条件时才为真
Includes
是否包含某个对象
Select
获取符合条件的一个子集
Reject
减去符合条件的一个子集
IsEmpty
集合为空
NotEmpty
集合不为空
此外,ECOⅡ对集合操作还有增强,如提供了sum、avg、max、min的聚集操作函数,同时它还支持多种非聚集函数,如concat、length、toupper、tolower等。
其它的一些特性:
特性
OCL
OPath
NULL判断
支持
支持
Implies(表示如果左边为真,那么右边也要为真)
支持
A implies B可以转化为(A and B) or (Not A)
类型判断和转换
支持
无
Distinct
支持(通过Set集合返回)
不支持(因为只是对象获取和属性过滤,没有集合操作,所以不涉及到子集合,而外部对象集合一般有主键约束)
集合内元素获取
支持
不支持
Order By
支持
不支持,但可以通过调用查询对象的方法达到目的
假如增强OPath的话,大概会是什么样子?
如果要支持集合操作的话,那么现有的OPath语法的简单性肯定要大打折扣,比如说类似于OCL中的forAll,OPath如果要实现的话,可能的方法就是:
(Employees[salary > 3000].Count = Employees.Count)
性能比较
因为现在ObjectSpaces中的OPath语句最后都将转为SQL执行,所以它的性能是非常好的(时这也正是它功能无法强大的弱点),而OCL的语法只有部分才能转化为SQL,因此在ECOⅡ中,还有部门的OCL操作必须针对内存对象来进行,这样也就使得必须装载大量的实体对象到内存中。
你将选择哪种查询?
就我个人而言,我倾向于增强型的OPath。毕竟更加复杂的查询我们可以通过view和store procedure来完成,就算OCL再强大,也无法涵盖我们需要的查询功能,其内存对象操纵的性能问题不能不让我们谨慎使用,而ECOⅡ可以算是一个MDA的框架,这也让我对MDA的将来感到一些担忧,除非ANSI SQL进化到了可以更加强大的地步,各数据库本身就可以完成OCL所需要的查询功能,但这个时候,也许SQL的表达更加直观,那么,我们又为什么需要OCL来查询呢。当然,OCL在UML中的作用我们并不否定,只是直接从模型生成代码的应用似乎只能在不太复杂的场合才生效。
(注:因为ECOⅡ的资料很少,很多是参考它的前身bold for delphi的语法,而OPath的资料也少,很多都是无关痛痒的简单操作,这让人弄不明白到底是它的语法就这么简单还是另有其它的增强。) |
|
|