当你还在纠结于ORM的性能时,我已经远远的把你抛在脑后
最近找工作面试,问到一些过去的工作和项目经验。我把公司用到的ORM框架(LLBL Gen)拿出来谈一谈,说一下他的优势,对方却一直追问ORM的好处,性能方面的问题,让我有时候都不知道如何回答,产生了不小的压力。
坦白来说,自学生时代(2004)就对NHibernate的大名敬仰已久,也完整的学习过它的映射文件写法,数据读取方法,当时对复杂的Xml映射配置文件了熟于胸。那时,微软的Application Block还比较流行,这项技术演变为后来的Enterprise Library,在第二份工作,我可以参与技术选型时,毫不犹豫的选择了Enterprise Library。再配合一个实体代码生成工具,工作中的技术需求都可以应对。再接下来的一份工作,选择ORM数据访问,再应用一些熟悉的技术,一下子对整个MIS类型项目的开发设计有了更基础层面的理解。如果需要了解,请参考
Enterprise Solution 2.2 开发帮助文档集合
ORM到底有什么好处,以我的理解有以下三点
1 强类型的对象 界面和业务逻辑层以实体对象来作为传输格式,编译器在编译时就可以辅助帮忙检查类型错误,而不需要等到运行时。
2 借助于数据绑定技术,业务逻辑层与界面层完全分离。ASP.NET MVC现在是教导你强制分离,并且创建好了基础结构,只需要遵循它的开发模式,即可开发出界面与逻辑分离的程序。但在WinForm时代,我承认,在之前,我是用很原始的方式,在窗体加载(OnLoad)时把数据绑定到控件,在点击按钮执行动作时,再从控件读取数据,传到逻辑计算方法中。强类型配合数据绑定技术,在界面加载时,传递一个entity到界面中,在执行动作时,获取数据源中的entity,可以节省大量的代码。
3 可扩展性,可维护性增强。如果有数据库字段修改,因为传递的是entity对象,数据访问接口不需要做任何修改,而界面中只需要把相关的字段绑定到控件中即可。MIS类型的项目,表格或字段的增加与减少是常有的事,而需要做的就是重新生成一次实体定义代码,绑定字段到界面中,增加需要的计算逻辑即可。
因为ORM框架会自带一些基础的类型(元数据)和数据访问方法,因而还可以做出很多基础性的工作。举例如下:
1 插件式系统的功能管理。管理基础的模块和功能。
2 定义一套权限结构。用户管理,用户组别管理,模块权限,功能权限,具体的数据字段权限与业务绑定。
3 定义一套查询框架。MIS类型的系统,在系统提供基础查询的基础上,要让用户可以自定义查询。在这点上,只需要获取ORM的entity与数据库中的table映射关系,放到基础的查询表中,再依照此实体,反射它的属性成员供用户选取查询,最后生成一个查询表达式,运行时转化成SQL语句从数据库中读取数据。
4 定义一套报表框架。因为报表是经常会发生变化的。报表的布局,参数,数据来源,计算逻辑都会依照实际的需求产生一些变化。程序员需要将报表开发中,不会改变的地方独立出去,做成一个公共模块,供报表开发人员调用。这一块内容,我做到了将用户输入值与与报表参数动态绑定。
5 导航设计工具。MIS项目如果要满足用户自定义菜单,导航功能的需求,则需要实现一套菜单结构定义。存储的格式为Xml或是数据库,在运行时,依据定义生成界面中的菜单和导航,增加灵活性。
6 工作流绑定。因为强类型的entity,它的create,delete,update动作都可以通过读取元数据得知,包括属性值的变更,以反射的方式读取。可以截获特定的值改变事件,比如采购单批准(approved)这个值设为yes,激活工作流,自动生成一些数据通知或查询结果,发送到指定的负责人。
性能层面,ORM肯定不及原生的ADO.NET,映射转换从entity到table都需要消耗一定的时间。经过优化的ORM查询,性能损失不比ADO.NET慢很多,但是得到的好处是易于维护,以及因此而带来的一系列的技术提升,前提是你不仅仅把ORM拿来做数据访问,还研究它的元数据结构,与数据绑定技术的融合等技术。
四年以前开发MIS类型的项目,从创建数据表开始,再借助于代码生成器,生成实体和数据访问代码,再到逻辑层开发。在经历上一份工作之后,经过这几年的积累,我也做到了快速开发,不过这次的格调也高很多。用企业架构模式中的话来说,前一种是事务脚本(transaction script),后一种是领域模式(domain model)。
最后写两句话与大家共勉励:
1 适合完成项目的技术是最好的技术,一味追求技术更新会给项目带来风险。
2 当你在习惯于一种开发模式后,在有精力或是项目允许的情况下,可以考虑尝试另一种技术路线。