置疑纯ORM方案

来源:互联网 发布:淘宝网络推广的方法 编辑:程序博客网 时间:2024/05/10 02:58
纯orm方案的缺点:
处理复杂对象查询时有难度。数据模型中的所有表格及关系很复杂,包括关联、引用(也就是主从表)和继承三种关系,甚至包括嵌套的复杂关系,在做or mapping的时候非常复杂。
对应于表中的连接查询,如果直接写sql语句违背了map 规则,不写,灵活度不够。虽然在一些ORM方案中也可以把数据库表之间的关系也映射到对象层里,但是这样在数据库和数据访问层之间增加了一个映射层,再说了映射用的元数据都是XML格式的,访问这个XML文件的时候还得做额外操作,性能肯定要降低了(当然可以在应用程序启动的时候把元数据都缓存起来)。而且那个什么Opath语言,我看不出来和t-sql相比,他有什么优势,Xpath是查询XML用的,它用来查询Object,但是它的Opath查询,最后还是得转换成SQL来查询数据库呀,而且很可能一条Opath语句查下去可能得生成好几条SQL语句,而且它生成的SQL语句有你自己写的语句可靠吗,有你自己写的sql语句性能好吗?我看呀,以后这人们就都不用学sql了,直接学这个Opath就行了,到时候只有高手才会写SQL语句,就象初学者只会调用.NET封装好的类一样,而不知道这些类是怎么封装了COM和API的。我不是说这不好哦,这样做入门是简单了,可是人们被迷惑了似的,多年以后肯定只有微软自己的人才知道这些类的实现原理,而人们想接触一下底层的东西就很难了,我担心有一天我们的精力不够了,从懂事就开始学编程,一直学到40岁了才算入门,还啥都用不上,因为知识太多了,要想实现一个简单程序就得学10几年的知识,这不是悲哀吗,呵呵,撤远了哦。

下面说说我的想法哦:
我感觉将关系数据映射到业务实体,还是手工或者半手工做的比较好,因为你完全靠工具来生成OSD,RSD,MSD这些文件肯定不能完全覆盖你在领域分析后得出的问题域,工具哪儿有人智能呀,人有时候还分析不出来呢?

而数据库层面的的业务逻辑实现(细粒度的)还是用存储过程来做比较好,而靠Opath这类的语言生成的sql语句肯定不能达到最优化(你能相信DataAdapter自己生成的数据更新sql语句吗?还是使用自定义命令呀?),而且在集合处理方面还存在问题(你说在内存里建立1000个对象的实例和建立一个有1000行的DataTable哪个开销大?),orm是建立在ADO.NET之上的,以后人们是不是连ADO.NET也不用学了呀,直接把对象组成的ArrayList绑定到DataGrid上呀?

现在这人是越来越懒了,我感觉写一个程序最重要的工作还是业务建模和写业务层的代码,这个层的代码估计除了MDA没什么工具可以生成的吧(个人感觉MDA也不是很合适的软件开发方法)?当然了,向orm这些东西属于次要复杂性,本应该是由工具和语言来完成,而不应该耗费程序员的精力(谁也不会否定面向对象的软件开发比结构化编程有优势,谁也不会否定递归算法很巧妙,尽管它耗费资源),但是我感觉还没成熟到那种全自动的程度吧,在全自动生成和全手工编写之间我们得找一个平衡点儿。

我们的目标是在数据库从sqlserver换成oracle,一个表里增加了两个字段的时候,客户要求再给某个对象增加一个方法的时候我们只要改动数据访问层和业务实体层就可以了,而尽量不改动业务层和表示层的代码,也就是维护方便。我们想利用ORM来达到这种效果,我们认为数据实体层和数据访问层只改动元数据就可以完成维护工作了,可是这些东西用了大量的反射(性能降低了),而业务层代码和UI不用改了吗,这怎么可能呢?你数据表里增加个字段,你的业务层的方法签名不需要改吗(就算你用业务实体(业务实体根据xml确定)做传入参数,但是方法里面处理的时候你不得变呀)?还有你的界面显示的时候不还得变呀,你不做客户端的数据验证代码了吗?这问题多着呢,哪儿能那样一劳永逸呀?现在还除了好多代码生成的工具,甚至界面也能靠XML生成了,人都考虑不过来的东西,让工具去考虑,真是的。

我想我们一定是厌倦了在c#里写那么多重复繁琐的sql处理代码了,我们是想把处理sql或者存储过程的这些代码自动化,我们不想为每个存储过程的调用手工创建一大堆参数,然后给参数赋值,然后再调用DAAB执行,还得考虑参数缓存什么的,我们肯定讨厌这些重复工作了,我们想存储过程修改(无论是存储过程本身改变还是从sql的存储过程改变成oracle的存储过程)后我们的数据访问层能自动适应,自动创建参数,自动赋值。如果想这样,就得给存储过程建立元数据,而不是给表建立元数据,表对应的是Object(实际物体,订单啦,产品啦),而存储过程对应的是Action(例如增加或者取消一个订单)或者Service(例如根据某个条件来生成一个DataView)的数据层实现,当然有人说了“随着在存储过程中实现的业务逻辑的增多,存储过程可以简化维护带来的优势会逐渐减弱”,可是那也比纯用Opath这类更高层次的语言来实现数据访问有优势吧,再说了存储过程只封装细粒度的业务逻辑,返回简单处理后的数据,然后由数据层经过复杂处理才提供给业务层的。我估计光Opath也不能完成粗粒度的业务逻辑吧,也得把结构提供给业务层吧?

我设想了一个架构(抄的,不过感觉很灵活):
MonitorServices:负责监控和跟踪。
MonitorServicesLogging:负责日志记录和错误处理。
ConfigurationServices:负责配置服务,从.config里读取配置数据。
CMPServices:提供CMP处理
这几个项目提供底层服务,微软发布了7中企业开发模块,里面几乎都包含了上面我提到的这些东西(除了最后一个),我感觉我提出的这几个是必要的,比较通用,加密解密和缓存是可选的,有的项目里用不到吧,看项目需要再做添加。

别的好说,微软的企业开发模块里都包括了,在设计模式和实际操作上都给了一些指导,微软好像有视频下载,下载下来看看,理解一下,再参考MSDN的类库开发人员指南,写出自己的类库就行了。
着中看一下CMPServices类库,在这里执行操作存储过程,首先肯定得有个类负责读取存储过程的元数据,元数据里包括了存储过程的名字,参数的信息,以及对应的业务实体类(业务实体类可以用代码生成器生成再改改),这些元数据放在.config里,如果这些东西改了,调用存储过程的代码自动就改了。而不象petshop里那样为oracle和sqlserver写两个dal层,然后用通过接口和工厂类来确定使用哪个类库,这还算好的,普通的方案的BLL层里调用DAL层的方法的时候用的是RunSqlserverSP(strSP)或者RunOracleSP(strSP)这样的方法,DAL层和BLL层是紧密耦合,这些都属于托管组件持久性(Component Managed Persistence),而我想用的是托管容器持久性(Container Managed Persistence)。当然这个类库里还要设计好几个类来提供业务实体的持久性,简单介绍一下。
CMPConfigurationHandler:读取.config里的XML数据生成容器映射和命令映射类,并缓存起来。
CommandMapping:命令映射类,存储过程的名称,参数等,对应一个命令。
CommandParameter :存储过程的参数,包括参数的类型,长度,方向等
ContainerMapping :容器映射类。
ContainerMappingSet :一组容器映射类。
PersistableObject :持久类,和业务实体类差不多。
PersistableObjectSet 一组业务实体类,如果一个select语句返回1000个记录,与其生成1000个PersistableObject的实例,不如保存在Dataset里。
StdPersistenceContainer:这是个容器基类,定义实现容器映射的成员,每个容器可以执行CRUD四个命令。
SqlPersistenceContainer :sqlserver的容器实现类,这里利用反射和XML元数据来建立存储过程元数据和持久类之间的关系。

写业务逻辑层的时候可以实力一个容器,然后调用容器的CRUD命令来执行操作,实际上这就是去执行存储过程了,而存储过程里你再去写更细的逻辑,给CRUD命令传递参数的时候可以把这个容器对应的持久类的实例传进去,然后容器自己就会处理持久类实例的属性和存储过程参数的对应关系。这样就相当于把存储过程包装起来了,也在持久对象和数据库间建立了一个层,但这个层比纯ORM的方案灵活吧,你也不用opath这类晦涩的语言执行关系数据库查询,存储过程你爱怎么写怎么写,只要能灵活应用这种架构,就能适应无穷无尽的业务逻辑。如果数据库变了,至少在数据访问层可以做很小修改就能完成维护工作,改元数据呗,至于由于数据库变化导致的业务层和其它中间层,显示层的改动可以通过其它技巧减少一些,肯定不可能一劳永逸的,我们差完全自动生成代码还远呢,你的基础架构越强大,灵活性就越差我感觉,因为动些越多,耦合性越强,到时候架构功能太多,我想去一项服务也不行,本身就难以维护了,是吧,就象.NET框架,部署的时候还得把它部署进去,20多M的东西,我写一愕几十K的程序得部署一个20多M的框架,我能不生气吗?

别人置疑.NET社区,偶就来置疑一下纯ORM吧,呱呱。
 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1505912


原创粉丝点击