上一篇《我的框架(9)——关于默认值》中说到关于默认值的想法,得到了一些有意思的反馈。我一直很纳闷,为什么只有在自动生成的SQL语句中支持默认值,才是自动化呢?既然是程序员,既然有OO,还有代码生成器,为什么不自己动手,把该做的事情做掉呢?不过既然有人提出这个问题,我也还是来说明一下实现的方式(虽然我不想在自己的框架里实现)。

 

对于这个问题,必须从两个方面考虑:1、像我这样有管理状态和历史数据的实体模型。2、不管理状态且没有历史数据的实体模型。

对于有状态管理和历史数据的实体模型,要实现默认值其实很简单。因为保存了最原始的数据备份,所以在生成SQL语句的时候只需要和原始数据进行对比。如果属性的值进行过修改,则生成对应该字段的SQL语句,否则不生成对应该字段的SQL语句。所以也没有什么需要特别描述的东西。不管理状态且没有历史数据的实体模型,要实现默认值就会复杂一些。关键看实体的实现方式,从基类继承还是不继承。不过其实也大同小异,最多就是动态代理上完成本应该由基类完成的东西。建立一个字典或其他什么,记录每个属性是否被修改过。如果修改了,则生成对应该字段的SQL语句,否则不生成对应该字段的SQL语句。如此一来,所谓的数据库默认值的问题就解决了。

 

本来还想多写点,不过实在不知道还有什么关于实现的东西好写。所以,还是再详细叙述一下为什么本人不想支持默认值。

ORM提高效率的一个方式就是用Emit代替反射,并将一些常用的方法(如:比较、映射)在生成之后缓存起来,避免重复劳动。对于相同类型的实体,只要第一次生成,以后直接从缓存中取得已有的方法就好,从而省略每次都重复生成的耗费。如果希望支持数据库的默认值,必然需要在每次更新的时候比较数据是否进行过修改,并根据比较的结果生成SQL语句。由于SQL语句不同,如果使用参数,每次对参数赋值的方法也会有所区别。也就是说,除了生成SQL语句的耗费外,还得加上生成参数,以及对参数赋值的耗费。每次将实体数据更新都必须如此操作,批量更新的时候这样的耗费累加起来就不算小了。在web项目中性能的对比效果可能更加明显,第一个用户进行更新后,其他用户都不必再做重复工作了生成工作了。

DefaultValueAttribute或者其他CustomAttribute作为设置默认值的手段,也不是很好用。因为CustomAttribute中的参数仅支持常量表达式。要想做到DateTime.Now这样的默认值就比较困难了。虽然也可以用DynamicMethod,但毕竟没有直接写代码那么灵活,效率也没有那么高。而且说实话,用Customattribute和直接写代码相比,在敲键盘的次数上来说,并不会差太多。

 

最后,发一下感想。

框架本身只是一种辅助。并不因为某一个框架能让你偷懒比较多就说明它比去其他的框架都要有效。框架所做的事情只是让使用者远离错误和混乱,帮助使用者逃离了一些不必要的错误和混乱之后,自然能提高使用者的效率。更何况,现在有OOORM、代码生成器、优秀的IDE、完善的编译时检查,为什么一定要去做一些不是很有必要的投机取巧的工作呢?

posted @ 2009-11-26 14:21 陈鹏(偶是坏人) 阅读(1380) 评论(2) 编辑