我们做项目的时候几乎每个项目都会有代码表(只有键和值两个字段的数据表),很多代码表都是需要维护的,如果我们每个都从新开始编码那将浪费大量时间。我今天有空就写了一个小的解决方案,但发现了大量的问题,下面一一讲述:
先假设有单位表(表名:DanWei,PK:ID,ValueField:Name),职位表(表名:ZhiWei,PK:ID,ValueField:Name),职称表(表名:ZhiCheng,PK:ID,ValueField:Name),他们都需要进行增删改的操作。当然有时候一个项目有上十个或更多的代码表需要维护。
这个示例是WebForm采用了3层架构。数据层为:DataAccess,业务层为:DataBusiness,表现层为:WebProject。
我先写了一个代码表操作的基类,代码如下:
1
/// <summary>
2
/// 只有键、值两个字段的数据维护的基类。只能被继承,不能实例化
3
/// </summary>
4
public abstract class clsDictCodeBase : ClassBase
5
{
6
属性
47
48
/// <summary>
49
/// 通过ID更新记录
50
/// </summary>
51
/// <param name="ID">主键</param>
52
/// <param name="NameValue">更新后的值</param>
53
public virtual void UpdateRecordByID(int ID, string NameValue)
54
{
55
try
56
{
57
dbCtrl.cmd_Execute("Update " + TableName + " set " + ValueField + "=@NameValue where " + PKField + "=" + ID
58
, new SqlParameter("@NameValue", NameValue));
59
}
60
catch (Exception ex)
61
{
62
throw ex;
63
}
64
}
65
66
/// <summary>
67
/// 通过ID删除一条记录
68
/// </summary>
69
/// <param name="ID">要删除的ID</param>
70
public virtual void DeleteRecordByID(int ID)
71
{
72
try
73
{
74
dbCtrl.cmd_Execute("Delete from " + TableName + " where " + PKField + "=" + ID);
75
}
76
catch (Exception ex)
77
{
78
throw ex;
79
}
80
}
81
82
/// <summary>
83
/// 插入一条记录
84
/// </summary>
85
/// <param name="Name">值</param>
86
public virtual void InsertRecord(string Name)
87
{
88
try
89
{
90
dbCtrl.cmd_Execute("Insert into " + TableName + "(" + ValueField + ") values(@ValueName)",
91
new SqlParameter("@ValueName", Name));
92
}
93
catch (Exception ex)
94
{
95
throw ex;
96
}
97
98
}
99
100
/// <summary>
101
/// 通过ID选出一条记录
102
/// </summary>
103
/// <param name="ID">主键</param>
104
public virtual System.Data.DataTable SelectByID(int ID)
105
{
106
try
107
{
108
return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " where ID=" + ID);
109
}
110
catch (Exception ex)
111
{
112
throw ex;
113
}
114
}
115
116
/// <summary>
117
/// 通过Name选出记录
118
/// </summary>
119
/// <param name="Name">Name</param>
120
public virtual System.Data.DataTable SelectByName(string Name)
121
{
122
try
123
{
124
return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " where " + ValueField + " like '%'@Name'%' order by " + PKField + " desc",
125
new SqlParameter("@Name", Name));
126
}
127
catch (Exception ex)
128
{
129
130
throw ex;
131
}
132
}
133
134
/// <summary>
135
/// 选出所有记录
136
/// </summary>
137
public virtual System.Data.DataTable SelectAll()
138
{
139
try
140
{
141
return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " order by " + PKField + " desc");
142
}
143
catch (Exception ex)
144
{
145
throw ex;
146
}
147
}
148
149
}
/// <summary>2
/// 只有键、值两个字段的数据维护的基类。只能被继承,不能实例化3
/// </summary>4
public abstract class clsDictCodeBase : ClassBase5
{6
属性47

48
/// <summary>49
/// 通过ID更新记录50
/// </summary>51
/// <param name="ID">主键</param>52
/// <param name="NameValue">更新后的值</param>53
public virtual void UpdateRecordByID(int ID, string NameValue)54
{55
try56
{57
dbCtrl.cmd_Execute("Update " + TableName + " set " + ValueField + "=@NameValue where " + PKField + "=" + ID58
, new SqlParameter("@NameValue", NameValue));59
}60
catch (Exception ex)61
{62
throw ex;63
}64
}65

66
/// <summary>67
/// 通过ID删除一条记录68
/// </summary>69
/// <param name="ID">要删除的ID</param>70
public virtual void DeleteRecordByID(int ID)71
{72
try73
{74
dbCtrl.cmd_Execute("Delete from " + TableName + " where " + PKField + "=" + ID);75
}76
catch (Exception ex)77
{78
throw ex;79
}80
}81

82
/// <summary>83
/// 插入一条记录84
/// </summary>85
/// <param name="Name">值</param>86
public virtual void InsertRecord(string Name)87
{88
try89
{90
dbCtrl.cmd_Execute("Insert into " + TableName + "(" + ValueField + ") values(@ValueName)",91
new SqlParameter("@ValueName", Name));92
}93
catch (Exception ex)94
{95
throw ex;96
}97

98
}99

100
/// <summary>101
/// 通过ID选出一条记录102
/// </summary>103
/// <param name="ID">主键</param>104
public virtual System.Data.DataTable SelectByID(int ID)105
{106
try107
{108
return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " where ID=" + ID);109
}110
catch (Exception ex)111
{112
throw ex;113
}114
}115

116
/// <summary>117
/// 通过Name选出记录118
/// </summary>119
/// <param name="Name">Name</param>120
public virtual System.Data.DataTable SelectByName(string Name)121
{122
try123
{124
return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " where " + ValueField + " like '%'@Name'%' order by " + PKField + " desc",125
new SqlParameter("@Name", Name));126
}127
catch (Exception ex)128
{129

130
throw ex;131
}132
}133

134
/// <summary>135
/// 选出所有记录136
/// </summary>137
public virtual System.Data.DataTable SelectAll()138
{139
try140
{141
return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " order by " + PKField + " desc");142
}143
catch (Exception ex)144
{145
throw ex;146
}147
}148

149
}其中这个类是个抽象类,里面都是虚方法和属性,将这个类写成虚类就是防止用户在表现层里实例化。这里面将要操作的表名和字段名写成了虚属性,以便通用。
现在写了一个单位的代码表维护类,类似于这样的类的个数依数据表的个数而定,现只贴出一个示例。代码如下:
1
/// <summary>
2
/// 单位代码表管理的业务类
3
/// </summary>
4
public class clsSocietiesMng : clsDictCodeBase
5
{
6
public clsSocietiesMng()
7
{
8
}
9
10
/// <summary>
11
/// 通过ID更新一条社团记录
12
/// </summary>
13
/// <param name="ID">主键</param>
14
/// <param name="NameValue">更新后的值</param>
15
public void UpdateSocietyByID(int ID, string NameValue)
16
{
17
try
18
{
19
UpdateRecordByID(ID, NameValue);
20
}
21
catch (Exception ex)
22
{
23
throw ex;
24
}
25
}
26
27
/// <summary>
28
/// 通过ID删除一条社团记录
29
/// </summary>
30
/// <param name="ID">要删除的ID</param>
31
public void DeleteSocietyByID(int ID)
32
{
33
try
34
{
35
DeleteRecordByID(ID);
36
}
37
catch (Exception ex)
38
{
39
throw ex;
40
}
41
}
42
43
/// <summary>
44
/// 插入一条社团记录
45
/// </summary>
46
/// <param name="Name">值</param>
47
public void InsertSociety(string Name)
48
{
49
try
50
{
51
InsertRecord(Name);
52
}
53
catch (Exception ex)
54
{
55
throw ex;
56
}
57
58
}
59
}
这个类继承自上面所写的代码表操作的基类,但并没有override其中的Virtual方法,因为这里没必要override,同时新增了3个方法。我本想将这个类也写成
/// <summary>2
/// 单位代码表管理的业务类3
/// </summary>4
public class clsSocietiesMng : clsDictCodeBase5
{6
public clsSocietiesMng()7
{8
}9

10
/// <summary>11
/// 通过ID更新一条社团记录12
/// </summary>13
/// <param name="ID">主键</param>14
/// <param name="NameValue">更新后的值</param>15
public void UpdateSocietyByID(int ID, string NameValue)16
{17
try18
{19
UpdateRecordByID(ID, NameValue);20
}21
catch (Exception ex)22
{23
throw ex;24
}25
}26
27
/// <summary>28
/// 通过ID删除一条社团记录29
/// </summary>30
/// <param name="ID">要删除的ID</param>31
public void DeleteSocietyByID(int ID)32
{33
try34
{35
DeleteRecordByID(ID);36
}37
catch (Exception ex)38
{39
throw ex;40
}41
}42

43
/// <summary>44
/// 插入一条社团记录45
/// </summary>46
/// <param name="Name">值</param>47
public void InsertSociety(string Name)48
{49
try50
{51
InsertRecord(Name);52
}53
catch (Exception ex)54
{55
throw ex;56
}57

58
}59
}抽象类的,但是如果那样做了就没办法实例化了,这是个问题,下面将会提到。我确实不想这个类被用户在表现层实例化,因为这个类里面涉及到了表名和字段名。所以我打算写一个工厂类去实例化它们。
工厂类代码如下:
1
代码表名称的枚举
17
18
/// <summary>
19
/// 创建clsSocietiesMng的实例
20
/// </summary>
21
/// <returns></returns>
22
public static clsSocietiesMng CreateSociety()
23
{
24
string strClassName = _strSocietyPath + ".clsSocietiesMng";
25
26
clsSocietiesMng codeOperator = (clsSocietiesMng)Assembly.Load(_strSocietyPath).CreateInstance(strClassName);
27
codeOperator.TableName = "DanWei";
28
codeOperator.PKField = "DanWeiID";
29
codeOperator.ValueField = "DanWei";
30
31
return codeOperator;
32
}
33
}
这个类现在不能说是一个工厂,待会我就说为什么我没有将其写成一个工厂类。这个类负责去实例化上述那些代码表操作类,同时给数据表名,字段名属性赋值,防止在表现层出现数据表名和字段名等。
代码表名称的枚举17

18
/// <summary>19
/// 创建clsSocietiesMng的实例20
/// </summary>21
/// <returns></returns>22
public static clsSocietiesMng CreateSociety()23
{24
string strClassName = _strSocietyPath + ".clsSocietiesMng";25

26
clsSocietiesMng codeOperator = (clsSocietiesMng)Assembly.Load(_strSocietyPath).CreateInstance(strClassName);27
codeOperator.TableName = "DanWei";28
codeOperator.PKField = "DanWeiID";29
codeOperator.ValueField = "DanWei";30

31
return codeOperator;32
}33
}但由于我的这些代码表操作类都没有继承自一个统一的接口所以不能用一个工厂方法去自动实例化这些类,而必须去一个一个地写成方法。
这样写成3个类后用户在表现层如下使用:
1
clsSocietiesMng society = clsDictCodeControl.CreateSociety();
2
society.UpdateRecordByID(1,"aaa'aaa");
虽然如第一行所示,可以采用clsDictCodeControl.CreateSociety();方法去实例化一个实例,但是用户同样可以直接clsSocietiesMng society = new clsSocietiesMng();去实例化一个实例,我不想让用户直接在表现层通过clsSocietiesMng society = new clsSocietiesMng();去实例化。我想将clsSocietiesMng之类的处理类写成抽象类但是那样不行,这个问题还真不知道怎么去解决呢。
clsSocietiesMng society = clsDictCodeControl.CreateSociety();2
society.UpdateRecordByID(1,"aaa'aaa");处理类这样写让我觉得有些问题解决的不好:
1 用户在表现层同样可以自己去实例化(例如:clsSocietiesMng society = new clsSocietiesMng())而不用实例方法(clsDictCodeControl.CreateSociety();)。这点让我决得很不好,但我不知道怎么去解决。
2 这个工厂类应该变成一个真正的简单工厂类,而不是现在的这个样子。
以上两个问题是我觉得最严重的问题。当然这个方案里面还存在这其它的问题就不一一列举了,我这里给出我的解决方案只是起一个抛砖引玉的作用,希望大家能提出更好的解决方案。

浙公网安备 33010602011771号