ORM(对象关系映射) ,在我们印象中Hibernate是体现的比较明显的。因为它的轻量级和低入侵式,得到很多IT人士的亲睐。
正是因为ORM 这种映射关系,使程序各个模块之间的耦合度大大降低,使得程序灵活多变。.NET 在Linq 出现之前几乎没有看到什么ORM映射框架,今年自己也.net 方面下了一番苦功夫学习,有小小成果就是自己写了一个ORM映射框架。在2009年的最后一天与大家分享
程序总体设计思路:
姑且用上面的图来表示整个框架的流程。其实就是用一些特性来描述实体和数据库之间的关系,当程序首次加载的时候,程序会去读取这些实体特性,并缓存到内存当中(这里使用的静态类来存储这些信息)。当用户提交表单封装实体之后,后面的实体解析类会根据各个不同的实体特性来组装一些sql语句,查询数据库并封装成实体对象或集合返回个客户端。
1.表特性类 TableAttribute
代码
1 /**
2 *
3 * 2009-4-11
4 *
5 *
6 * 表特性的信息
7 * */
8 using System;
9 using System.Collections.Generic;
10 using System.Linq;
11 using System.Text;
12
13 namespace CommonData.Model
14 {
15 public sealed class TableAttribute:Attribute
16 {
17 private string name;
18
19 /// <summary>
20 /// 表名称
21 /// </summary>
22 public string Name
23 {
24 get { return name; }
25 set { name = value; }
26 }
27 private string information;
28
29 /// <summary>
30 /// 表信息
31 /// </summary>
32 public string Information
33 {
34 get { return information; }
35 set { information = value; }
36 }
37 private bool isInternal;
38
39 /// <summary>
40 /// 是否国际化
41 /// </summary>
42 public bool IsInternal
43 {
44 get { return isInternal; }
45 set { isInternal = value; }
46 }
47
48 /// <summary>
49 /// 无参数构造方法
50 /// </summary>
51 public TableAttribute()
52 {
53 }
54
55 /// <summary>
56 /// 有参数构造方法
57 /// </summary>
58 /// <param name="name">表名称</param>
59 /// <param name="information">表信息</param>
60 /// <param name="isInternal">是否国际化</param>
61 public TableAttribute(string name, string information, bool isInternal)
62 {
63 this.name = name;
64 this.information = information;
65 this.isInternal = isInternal;
66 }
67 }
68 }
Hibernate 中是使用xml文件来实现实体类和数据库之间的关联,我这里是使用.net中的特性,当时是为了巩固自己所学习的知识,于是选择了特性。其实使用xml来实现数据和实体之间的映射更具灵活性。使用xml在程序部署之后,如果修改映射关系就不用重新编译。
TableAttribute 特性就是用来标识实体类和数据库表之间的关系的,表特性中包含了三个信息。以上代码都有说明,这里不再讲解。值得注意的是:这个类被sealed 修饰,说明这个类不能被继承。这里就将一定规则限制在某个范围内,避免不要的规则添加进来。
2. 列特性类 ColumnAttribute
代码
1 /**
2 *
3 * 2009-4-11
4 *
5 *
6 * 字段的特性
7 * */
8 using System;
9 using System.Collections.Generic;
10 using System.Linq;
11 using System.Text;
12
13 namespace CommonData.Model
14 {
15 public sealed class ColumnAttribute:Attribute
16 {
17 private string name;
18 /// <summary>
19 /// 字段名称
20 /// </summary>
21 public string Name
22 {
23 get { return name; }
24 set { name = value; }
25 }
26 private DataType type;
27 /// <summary>
28 /// 字段类型
29 /// </summary>
30 public DataType Type
31 {
32 get { return type; }
33 set { type = value; }
34 }
35 private int length;
36 /// <summary>
37 /// 字段长度
38 /// </summary>
39 public int Length
40 {
41 get { return length; }
42 set { length = value; }
43 }
44 private string instro;
45 /// <summary>
46 /// 字段介绍
47 /// </summary>
48 public string Instro
49 {
50 get { return instro; }
51 set { instro = value; }
52 }
53 private bool canNull;
54 /// <summary>
55 /// 字段是否可以为空
56 /// </summary>
57 public bool CanNull
58 {
59 get { return canNull; }
60 set { canNull = value; }
61 }
62 private object defaultValue;
63 /// <summary>
64 /// 默认值
65 /// </summary>
66 public object DefaultValue
67 {
68 get { return defaultValue; }
69 set { defaultValue = value; }
70 }
71 private bool primaryKey;
72 /// <summary>
73 /// 是否为主键
74 /// </summary>
75 public bool PrimaryKey
76 {
77 get { return primaryKey; }
78 set { primaryKey = value; }
79 }
80 private bool autoIncrement;
81 /// <summary>
82 /// 是否自动增长
83 /// </summary>
84 public bool AutoIncrement
85 {
86 get { return autoIncrement; }
87 set { autoIncrement = value; }
88 }
89
90 /// <summary>
91 /// 无参数构造方法
92 /// </summary>
93 public ColumnAttribute()
94 {
95 }
96
97 /// <summary>
98 ///
99 /// </summary>
100 /// <param name="name">字段名称</param>
101 /// <param name="type">字段类型</param>
102 /// <param name="length">字段长度</param>
103 /// <param name="instro">字段介绍</param>
104 /// <param name="canNull">字段是否可以为空</param>
105 /// <param name="defaultValue">默认值</param>
106 /// <param name="primaryKey">是否为主键</param>
107 /// <param name="autoIncrement">是否自动增长</param>
108 public ColumnAttribute(string name,
109 DataType type,
110 int length,
111 string instro,
112 bool canNull,
113 object defaultValue,
114 bool primaryKey,
115 bool autoIncrement)
116 {
117 this.name = name;
118 this.type = type;
119 this.length = length;
120 this.instro = instro;
121 this.canNull = canNull;
122 this.defaultValue = defaultValue;
123 this.primaryKey = primaryKey;
124 this.autoIncrement = autoIncrement;
125 }
126 }
127 }
这个特新用于修饰实体类的属性,映射表的各个字段。它和表特性是一样的,只不过修饰对象不同。表特性的各个字段属性在代码中都有说明。
3. 列特性类 LinkTableAttribute
代码
1 /**
2 *
3 * 2009-4-11
4 * 贺 臣
5 *
6 * 主表的特性
7 * */
8 using System;
9 using System.Collections.Generic;
10 using System.Linq;
11 using System.Text;
12
13 namespace CommonData.Model
14 {
15 public class LinkTableAttribute:Attribute
16 {
17 private string name;
18 /// <summary>
19 /// 主表的名称
20 /// </summary>
21 public string Name
22 {
23 get { return name; }
24 set { name = value; }
25 }
26 private string sqlPrefix;
27
28 /// <summary>
29 /// 前缀
30 /// </summary>
31 public string SqlPrefix
32 {
33 get { return sqlPrefix; }
34 set { sqlPrefix = value; }
35 }
36
37 private Type _tableType;
38
39 /// <summary>
40 /// 父表对象类型
41 /// </summary>
42 public Type TableType
43 {
44 get { return _tableType; }
45 set { _tableType = value; }
46 }
47
48 /// <summary>
49 /// 有参数构造方法
50 /// </summary>
51 /// <param name="name">主表的名称</param>
52 public LinkTableAttribute(string name)
53 {
54 this.name = name;
55 }
56
57 /// <summary>
58 /// 无参数构造方法
59 /// </summary>
60 public LinkTableAttribute()
61 {
62 }
63 }
64 }
这个特性也是用于修饰实体属性的,但是这个特性有些不同,它是用于修饰实体属性的。也就是某个数据库表对应的实体作为此实体的一个属性。利用该特性是使各个实体之间参数逻辑关系,用于替代数据库的物理逻辑关系。这里有个特殊的地方就是没有使用sealed 修饰这个特性类。因为维持实体之间的关系还有一个 1-N 得关系,也就是某个实体集合作为一个实体的一个属性。这样更能体现出数据结构之间的关系。
4. 列特性类 LinkTablesAttribute
代码
1 /**
2 *
3 * 2009-4-11
4 *
5 *
6 * 子表的特性
7 * */
8 using System;
9 using System.Collections.Generic;
10 using System.Linq;
11 using System.Text;
12
13 namespace CommonData.Model
14 {
15 public sealed class LinkTablesAttribute:LinkTableAttribute
16 {
17 /// <summary>
18 /// 无参数构造方法
19 /// </summary>
20 public LinkTablesAttribute()
21 {
22 }
23
24 /// <summary>
25 /// 有参数构造方法,调用父类的构造方法
26 /// </summary>
27 /// <param name="name">表名称</param>
28 public LinkTablesAttribute(string name)
29 : base(name)
30 { }
31 }
32 }
33
上面的代码可以看出,这个类继承了列特性 LinkTablesAttribute, 这也就是LinkTablesAttribute不适用sealed修饰的原意。两者本质区别在于一个修饰实体类,一个修饰实体类集合