业务逻辑层BLL实现过程
业务类使用DAL类提供对数据的访问,并加强验证规则,约束检查,并且提供数据的面向对象的表达方式和用于处理数据的方法。这样,BLL作为了一个映射层,它使得底层关系数据库中的数据在用户界面的代码中以对象的方式出现。
承接上文:DAL层代码实现
先来回顾:DAL中的实体类对象:User类和Department类
DAL中的实体类: 它们只是将从数据库中取得的数据象征性地进行封装,与数据库的表(或者视图)是一一对应的关系,
没有对数据进行插入、更新、删除和检索的方法。
建立BLL文件夹,里面存放的是业务域对象。下图是域对象DepartmentObj的类图。
这种类要复杂些,不但要封装数据,还要有对其父对象或子对象进行引用的其他属性(如DepartmentObj的属性AllUserObjs<表示该部门下的所有员工集合>;UserObj的属性DepartmentObj<表示该员工所属的部门信息>),还要有操作数据的实例方法<这些实例方法把工作委托给该类中各自对应的静态方法(如DeleteUserObj、UpdateUserObj等静态方法)>。(DepartmentObj/UserObj的Delete方法/Update方法)。
这种类通常称为域对象(domain object),而不仅仅是上面的实体类。虽然创建起来更复杂,但是能更好的将数据库结构抽象化,UI开发人员使用起来更直观。
域对象也比较容易维护,能更快地从数据库中载入数据,并且占用较少的内存,这是由于它利用了安需载入数据模式(lazy-load),只载入需要的数据,而不是将单个查询得到的所有内容同时载入。还可以为域对象增加自定义验证逻辑,因为数据是封装在能够充分按照自己所需要的逻辑来进行扩展的属性当中。
对应的代码如下:
DepartmentObj代码:
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using 抽象工厂模式.DAL.Provider;
5 using 抽象工厂模式.DAL.Entity;
6
7 namespace 抽象工厂模式.BLL
8 {
9 public class DepartmentObj
10 {
11 public DepartmentObj() { }
12 public DepartmentObj(int id, string name, string desc)
13 {
14 this.Id = id;
15 this.Name = name;
16 this.Desc = desc;
17 }
18
19 private int _id=0;
20 public int Id
21 {
22 get { return _id; }
23 set { _id = value; }
24 }
25 private string _name="";
26 public string Name
27 {
28 get { return _name; }
29 set { _name = value; }
30 }
31
32 private string _desc="";//部门描述
33 public string Desc
34 {
35 get { return _desc; }
36 set { _desc = value; }
37 }
38
39 private List<UserObj> _allUserObjs = null;
40 public List<UserObj> AllUserObjs
41 {
42 get {
43 if (_allUserObjs == null)
44 _allUserObjs = UserObj.GetUsers(this.Id);//按需载入(lazy load)模式
45 return _allUserObjs;
46
47 }
48 }
49
50 private static DepartmentObj GetDepartmentObjFromDepartment(Department record)
51 {
52 if (record == null) return null;
53 return new DepartmentObj(record.Id, record.Name, record.Desc);
54 }
55 private static List<DepartmentObj> GetDepartmentObjListFromDepartmentList(List<Department> recordset)
56 {
57 List<DepartmentObj> results = new List<DepartmentObj>();
58 foreach(Department record in recordset)
59 results.Add(GetDepartmentObjFromDepartment(record));
60 return results;
61 }
62 public static DepartmentObj GetDepartmentById(int id)
63 {
64 Department record= DepartmentProvider.Instance.GetDepartmentById(id);
65 return GetDepartmentObjFromDepartment(record);
66 }
67 public static List<DepartmentObj> GetDepartments()
68 {
69 return GetDepartmentObjListFromDepartmentList( DepartmentProvider.Instance.GetDepartments());
70 }
71 public static bool DeleteDepartmentObj(int id)
72 {return DepartmentProvider.Instance.DeleteDepartment(id);}
73 public static bool UpdateDepartmentObj(int id,string name,string desc)
74 {
75 return DepartmentProvider.Instance.UpdateDepartment(new Department(id,name,desc));
76 }
77 public static int InsertDepartmentObj(string name,string desc)
78 {
79 return DepartmentProvider.Instance.InsertDepartment(new Department(0,name,desc));
80 }
81
82 public bool Delete()
83 { bool success = DepartmentObj.DeleteDepartmentObj(this.Id); if (success) this.Id = 0; return success; }
84 public bool Update()
85 {
86 return DepartmentObj.UpdateDepartmentObj(this.Id, this.Name, this.Desc);
87 }
88 }
89 }
UserObj.cs代码:
1 using System.Collections.Generic;
2 using System.Text;
3 using 抽象工厂模式.DAL.Entity;
4 using 抽象工厂模式.DAL.Provider;
5
6 namespace 抽象工厂模式.BLL
7 {
8 public class UserObj
9 {
10 public UserObj(){}
11 public UserObj(int id, string name, int deptId, string deptTitle)
12 {
13 this.Id = id;
14 this.Name = name;
15 this.DeptId = deptId;
16 this.DeptTitle = deptTitle;
17 }
18 private DepartmentObj _departmentObj = null;
19 public DepartmentObj DepartmentObj
20 {
21 get {
22 if (_departmentObj == null)
23 _departmentObj = DepartmentObj.GetDepartmentById(this.Id);//按需载入(lazy load)模式
24 return _departmentObj;
25 }
26 }
27 private int _id;
28 public int Id
29 {
30 get { return _id; }
31 set { _id = value; }
32 }
33
34 private string _name;
35 public string Name
36 {
37 get { return _name; }
38 set { _name = value; }
39 }
40
41 private int _deptId;
42 public int DeptId
43 {
44 get { return _deptId; }
45 set { _deptId = value; }
46 }
47
48 private string _deptTitle;
49 public string DeptTitle
50 {
51 get { return _deptTitle; }
52 set { _deptTitle = value; }
53 }
54
55 private static UserObj GetUserObjFromUser(User record)
56 {
57 if (record == null) return null;
58 return new UserObj(record.Id, record.Name, record.DeptId, record.DeptTitle);
59 }
60 private static List<UserObj> GetUserObjListFromUserList(List<User> recordset)
61 {
62 List<UserObj> results = new List<UserObj>();
63 foreach (User record in recordset)
64 results.Add(GetUserObjFromUser(record));
65 return results;
66 }
67 public static List<UserObj> GetUsers()
68 {
69 return GetUserObjListFromUserList( UserProvider.Instance.GetUsers() );
70 }
71 public static List<UserObj> GetUsers(int deptId)
72 {
73 return GetUserObjListFromUserList(UserProvider.Instance.GetUsers(deptId));
74 }
75 public static UserObj GetUserById(int id)
76 {
77 return GetUserObjFromUser(UserProvider.Instance.GetUserById(id));
78 }
79 public static bool UpdateUserObj(int id, string name, int deptId)
80 {
81 return UserProvider.Instance.UpdateUser(new User(id, name, deptId, ""));
82 }
83 public static int InsertUserObj(int deptId, string name)
84 {
85 return UserProvider.Instance.InsertUser(new User(0, name, deptId, ""));
86 }
87 public static bool DeleteUserObj(int id)
88 {
89 return UserProvider.Instance.DeleteUser(id);
90 }
91
92 public bool Delete() { bool success = DeleteUserObj(this.Id); if (success) this.Id = 0; return success; }
93 public bool Update() { return UpdateUserObj(this.Id, this.Name, this.DeptId); }
94 }
95 }
进行测试:报错误,提示无法访问,检查发现:
很明显,忘记调用reader.Read()方法了,当使用DbDataReader对象的时候,千万不要忘记Read()方法的调用。
改动如下:
public override Department GetDepartmentById(int id)
{
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
var dbCommand = conn.CreateCommand();
dbCommand.CommandText =
"select id,[name],[desc] from department where id="+id;
conn.Open();
var reader = dbCommand.ExecuteReader();
if (reader.Read())
return GetDepartmentFromReader(reader);
else
return null;
}
}
其它地方对应改动,然后我们在看看lazy-mode模式的好处。
见图可知:窗体加载事件中的第一行代码:不会调用访问每个UserObj对象的属性DepartmentObj,但是当DataGridView控件呈现的时候会遍历UserObj对象的每个属性,自然访问了DepartmentObj属性,从而引起按需载入。<请注意:在UserObj的构造函数中:并没有对属性DepartmentObj进行读取。>
运行看断点执行情况:
接着F9,继续运行:
可见GridView显示每一行记录时,都会执行断点处代码:
最后显示:
当然,可以投机取巧一下(DataGridView显示的"抽象工厂模式.BLL.DepartmentObj"实际上是访问该对象的ToStriing()方法获取的。因为:基类Object有此虚拟方法),改写一下:
public class DepartmentObj
{
public override string ToString()
{
//return base.ToString();
return Name;
}
当来之世,经道灭尽,我以慈悲哀愍,特留此经止住百岁。其有众生,值斯经者,随意所愿,皆可得度。(南无阿弥陀佛)
道可道,非常道;名可名,非常名。
我常说,一个国家,一个民族,亡国都不怕,最可怕的是一个国 家和民族自己的根本文化亡掉了,这就会沦为万劫不复,永远不会翻身。---南怀瑾<国学大师>