自己动手写个ORM实现(2)
2008-05-26 10:07
423 查看
这里的做法源于手头的一个真实项目,就是数据处理模块应用了企业库,并没有引用诸如nhibernate,ibatis.net之类的orm框架,所以请注意到标题只是写个“orm实现”,目的就是为了对现有整体框架侵入性最小化的前提之下,将一些通用的crud操作封装成类似orm的处理方式。
很多朋友谈了关于重复“造轮子”的看法,大师们的“轮子”为了兼顾框架整体的通用性,不可能针对每个特定项目做处理,个人觉得我们应该从那些作品(诸如nhibernate)领悟他们的设计思想,然后结合工作中的实际情况,先自己动手做一做,从实践中体会,不失为一种好的学习方式。
关于主键是否采用自增方式,这也得看具体应用。毕竟,使用逻辑主键还是业务主键很久以来就存有争议,个人比较倾向于逻辑主键。
最后,自己动手只是学习的手段而不是本文的目的,实现的方法也并不一定适用于所有朋友的实际情况。希望能够”用20%的精力解决80%的问题“,仅此而已
回到正题
在前一节 自己动手写个ORM实现(1) 中,我们定义了实体接口IEntity,实现IEntity的抽象类EntityBase,以及建立实体-表, 属性-字段对应关系的EntityMappingAttribute以及PropertyMappingAttribute. 相应的,我们声明了一个简单的管理IEntity的接口IEntityManage,如下
public T Load<T>(int id) where T : IEntity
2//缓存实体类型对应表名
2 private static readonly Dictionary<Type, string> tnCache = new Dictionary<Type, string>();
3 //缓存实体属型对应的字段名
4 private static readonly Dictionary<PropertyInfo, string> fnCache = new Dictionary<PropertyInfo, string>();
5 //缓存实体类型的属性集合
6 private static readonly Dictionary<Type, List<PropertyInfo>> pCache = new Dictionary<Type, List<PropertyInfo>>();
作用也很简单明了,就是在一个EntityManager实例的作用域内维护对传入需要操作的实体对象的反射信息的缓存
完整的GetTableName<T>方法实现如下
1protected string GetTableName<T>() where T : IEntity
2protected T GetByDataRow<T>(DataRow data) where T : IEntity
2protected IEnumerable<PropertyInfo> GetMappedProperties<T>() where T : IEntity
2protected string GetFieldName(PropertyInfo property)
2this.SetPersistedStatus<T>(t, true);
SetPersistedStatus<T>方法就是设置我们IEntity接口的IsPersisted属性, 实体对象的持久化状态了.
实现如下
1private void SetPersistedStatus<T>(T t, bool persisted) where T : IEntity
2public List<T> LoadAll<T>() where T : IEntity
2protected List<T> GetByDataSet<T>(DataSet data) where T : IEntity
2 {
3 List<T> list = new List<T>();
4
5 if (data != null && data.Tables[0] != null)
6 {
7 foreach (DataRow row in data.Tables[0].Rows)
8 {
9 T t = GetByDataRow<T>(row);
10 if (t != null)
11 {
12 t.ID = Convert.ToInt32(row["ID"]);
13 list.Add(t);
14 }
15 }
16 }
17
18 return list;
19 }
到这里,我们EntityManager非常初步的查询功能(不涉及到条件查询,分页操作)就已经实现了,在后面的章节中我们将逐步实现其他功能.
很多朋友谈了关于重复“造轮子”的看法,大师们的“轮子”为了兼顾框架整体的通用性,不可能针对每个特定项目做处理,个人觉得我们应该从那些作品(诸如nhibernate)领悟他们的设计思想,然后结合工作中的实际情况,先自己动手做一做,从实践中体会,不失为一种好的学习方式。
关于主键是否采用自增方式,这也得看具体应用。毕竟,使用逻辑主键还是业务主键很久以来就存有争议,个人比较倾向于逻辑主键。
最后,自己动手只是学习的手段而不是本文的目的,实现的方法也并不一定适用于所有朋友的实际情况。希望能够”用20%的精力解决80%的问题“,仅此而已
回到正题
在前一节 自己动手写个ORM实现(1) 中,我们定义了实体接口IEntity,实现IEntity的抽象类EntityBase,以及建立实体-表, 属性-字段对应关系的EntityMappingAttribute以及PropertyMappingAttribute. 相应的,我们声明了一个简单的管理IEntity的接口IEntityManage,如下
public T Load<T>(int id) where T : IEntity
2//缓存实体类型对应表名
2 private static readonly Dictionary<Type, string> tnCache = new Dictionary<Type, string>();
3 //缓存实体属型对应的字段名
4 private static readonly Dictionary<PropertyInfo, string> fnCache = new Dictionary<PropertyInfo, string>();
5 //缓存实体类型的属性集合
6 private static readonly Dictionary<Type, List<PropertyInfo>> pCache = new Dictionary<Type, List<PropertyInfo>>();
作用也很简单明了,就是在一个EntityManager实例的作用域内维护对传入需要操作的实体对象的反射信息的缓存
完整的GetTableName<T>方法实现如下
1protected string GetTableName<T>() where T : IEntity
2protected T GetByDataRow<T>(DataRow data) where T : IEntity
2protected IEnumerable<PropertyInfo> GetMappedProperties<T>() where T : IEntity
2protected string GetFieldName(PropertyInfo property)
2this.SetPersistedStatus<T>(t, true);
SetPersistedStatus<T>方法就是设置我们IEntity接口的IsPersisted属性, 实体对象的持久化状态了.
实现如下
1private void SetPersistedStatus<T>(T t, bool persisted) where T : IEntity
2public List<T> LoadAll<T>() where T : IEntity
2protected List<T> GetByDataSet<T>(DataSet data) where T : IEntity
2 {
3 List<T> list = new List<T>();
4
5 if (data != null && data.Tables[0] != null)
6 {
7 foreach (DataRow row in data.Tables[0].Rows)
8 {
9 T t = GetByDataRow<T>(row);
10 if (t != null)
11 {
12 t.ID = Convert.ToInt32(row["ID"]);
13 list.Add(t);
14 }
15 }
16 }
17
18 return list;
19 }
到这里,我们EntityManager非常初步的查询功能(不涉及到条件查询,分页操作)就已经实现了,在后面的章节中我们将逐步实现其他功能.
相关文章推荐
- 自己动手写个ORM实现(4) 关于反射DataRow数据记录到实体性能的优化
- 自己动手打造ORM(五) —实现
- 自己动手写个ORM实现(3)
- 自己动手写个ORM 实现(1)
- 自己动手实现Expression翻译器 – Part Ⅲ
- 【数据结构与算法】自己动手实现图的BFS和DFS(附完整源码)
- 【自己动手写数据结构】 -- 有向带权图的邻接矩阵存储的简单实现
- 自己动手实现Android App插件化
- 自己动手实现纯Web远程监控系统(纯Web,跨浏览器)
- 练习:自己动手实现一个轻量级的信号量(二)
- [导入]自己动手实现 lucene 搜索代码高亮显示
- STL学习】自己动手C++编程实现hash table(散列表)
- 如何自己动手实现 KVO
- 自己动手写一个编译器Tiny语言解析器实现
- 自己动手实现一个Android Studio插件
- 自己动手重新实现LINQ to Objects: 4 - Range
- 【原创】自己动手实现JDK动态代理
- 自己动手重新实现LINQ to Objects: 11 - First,Last,Single以及它们带有OrDefault的重载
- 自己动手开发网络服务器(三):实现多线程
- 自己动手实现简易代码生成器、采用文本模板文件生成服务层、服务层接口代码的做法参考