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修饰的原意。两者本质区别在于一个修饰实体类,一个修饰实体类集合