在具体介绍我的ORM解决方案之前,先说一下没有该方案之前的状况:

还是我上篇post中提及的公司OA,上篇post中提到说当时用文件序列化的形式来存储数据,但用过文件序列化的人都知道,数据必须整存整取,为了存入新的数据,还必须先反序列化以前的数据,然后再重新序列化,因此如果要达到更新的目的,无论是整个实体对象,还是一个实体对象的某几个属性,都是很麻烦的事情。
经过一番思量,为了数据的安全性考虑,决定将该存储方案移植到数据库平台上,毕竟数据库更加高效,更加安全。在移植之前,也考虑过NHibernate,因为公司前几个项目都用NH作ORM方案,但仔细考量一番之后还是觉得,NH的实现方案太约束OO的思想,甚至可以说了屈就NH,原本可以很完美的OO实现也要委曲求全,本人就有在公司某一个项目中,另外写了很多包含原有Entity的Entitylogic类的经历,也就是说在只有属性,不具动作的NH生成Entity类另外加上方法。不知道园子里的兄弟对NH怎么个看法。
说了文件序列化和NH的实现,还是仔细来说一下我这两天的ORM实现。先简要的看一下架构图:
我的轻型ORM实现
可以看出在这张图中,我特意把Entities层画的短了很多,因为在我的DBImply中,根本就不需要用到Entities,而是利用反射去动态获取实体的属性信息,进而进行对象持久化。
详细解释我的实现之前,先简单说一下我对序列化实现的看法。为什么对象序列化之后对其进行反序列化,仍然能得到其关联对象的信息?我觉得莫非就是反射在其中作祟,而且m$在实现序列化时已经定义了一系列协议。
于是,在实现我的ORM方案时,根据我对序列化实现的想法,我确定了下面的协议:
1.类对象中,需要进行持久化的属性,必须定义自定义属性PersistAttribute//正如需持久化的类须定义Serializable属性一样
2.有关联关系的两个类,在其中之一定义AggregateRelationAttribute,并同时指明与之有聚合或组合关系的另一个类
//上述的两个Attribute都是我自定义的属性

在DBImply中,主要包含以下几个层次:
1.DynamicSqlBuilder
2.SqlCommandInvoker
3.DBImply
他们之间的关系可以用伪代码简要表示为:

我的轻型ORM实现IDataAccess da = new DBImply(entityObject);
我的轻型ORM实现
string sql = DynamicSqlBuilder.GetInstance().GetCRUDSqlString(entityObject);
我的轻型ORM实现
我的轻型ORM实现da.SqlCommandInvoker.InvokeCommand(sql);

其中关键部分就在DynamicSqlBuilder.GetInstance().GetCRUDSqlString(entityObject)中,因为ORM本身的实现瓶颈就在于如何对OO世界中的一个对象和二维表结构数据互相转换,只要有了数据库能读懂的Sql语句,一切都不再是问题。
于是,在这个GetCRUDSqlString方法中,我根据反射得到的对象信息,动态获取了数据库执行需要的CRUD的sql语句,下面略举Create为例:

        }

其中,PropertyPair是一个Name与Value相对应的类,用来对应表结构中的Column与Row的交集,定义如下

    }

通过调用上述的Insert构造器,便可动态获取与一个类对象有关的Sql语句了,后面的工作自然不用赘述。
当然,用人会说Sql注入怎么办?这个自然会在调用Sql构造器之前就有一个过滤,不用担心。

欢迎拍砖 我的轻型ORM实现 转载请申明来源!

相关文章: