看了asp.net time tracker starter kit的代码以后,觉得这个程序是学习面向对象编程开发的一个好案例。整个程序从功能上来讲就是记录人员参加项目工作的工时记录。分析得出主要有人员、项目、工时记录这几个类。整个程序正好是以这几个类为基础展开的。在业务逻辑层里ttuser(用户类)、project(项目类)和timeentry(工时记录类)分别就包括了对相应表的增、删、改等操作和整个程序中所用到的对这几个主要对象的各种操作。整个程序在类的划分和功能上做的很好,但是我觉得在三层架构的划分上不是很理想。
业务逻辑层包含的许多数据访问层的东西,如:数据库连接信息、用到的存储过程等。而这些信息我觉得放在数据访问层应该会更好一些。作为数据访问层,应该为数据逻辑层提供访问数据库的方法,而不是只提供一个简化数据访问的组件(daab)。假设要使用oracle数据,那么改动的代码就需要改动很多,同时也不利于将来的改动。
我的想法是:彻底的将与数据相关的操作从数据逻辑层分离出去,对数据访问层只提供访问方法。在数据访问层的设计上,还是沿用“为数据访问层编写一个基类”的方法,通过基类访问daab。这样一来如果要变换为oracle数据库,只要修改daab中的内容即可。大家帮忙看看我的改进代码,看看思路有无问题。
数据访问层基类:
using system;
using system.data;
//数据访问组件(用的微软提供的)
using mystarterkit.ddab;
namespace mystarterkit.timetracker.dal
{
/// <summary>
/// dalbase 的摘要说明。
/// 数据访问层积累
/// </summary>
public class dalbase
{
//数据库连接字符串
private string connstr = system.configuration.configurationsettings.appsettings[“connectionstring”];
public dalbase()
{
}
/// <summary>
/// 返回一个单值
/// </summary>
/// <param name=”commandtext”></param>
/// <param name=”parametervalues”></param>
/// <returns></returns>
protected object executescalar(string commandtext, params object[] parametervalues)
{
return sqlhelper.executescalar(connstr, commandtext, parametervalues);
}
/// <summary>
/// 执行无返回值操作
/// </summary>
/// <param name=”commandtext”></param>
/// <param name=”parametervalues”></param>
protected void executenonquery(string commandtext, params object[] parametervalues)
{
sqlhelper.executenonquery(connstr, commandtext, parametervalues);
}
/// <summary>
/// 返回dataset
/// </summary>
/// <param name=”commandtext”></param>
/// <param name=”parametervalues”></param>
/// <returns></returns>
protected dataset executedataset(string commandtext, params object[] parametervalues)
{
return sqlhelper.executedataset(connstr, commandtext, parametervalues);
}
}
}
数据访问层代码:(以项目类数据访问层代码为例)
using system;
using system.data;
namespace mystarterkit.timetracker.dal
{
/// <summary>
/// project 的摘要说明。
/// 项目信息类(数据访问层代码)
/// </summary>
public class project : dalbase
{
public project()
{
//
// todo: 在此处添加构造函数逻辑
//
}
/// <summary>
/// 获取全部的项目列表
/// </summary>
/// <returns></returns>
public dataset getallprojects()
{
return base.executedataset(“tt_listallprojects”);
}
/// <summary>
/// 获取项目列表
/// </summary>
/// <param name=”parametervalues”></param>
/// <returns></returns>
public dataset getprojects(params object[] parametervalues)
{
return base.executedataset(“tt_listprojects”,parametervalues);
}
/// <summary>
/// 删除项目
/// </summary>
/// <param name=”parametervalues”></param>
public void remove(params object[] parametervalues)
{
base.executenonquery(“tt_deleteproject”,parametervalues);
}
/// <summary>
/// 更新项目
/// </summary>
/// <param name=”parametervalues”></param>
public void update(params object[] parametervalues)
{
base.executenonquery(“tt_updateproject”,parametervalues);
}
/// <summary>
/// 新增项目
/// </summary>
/// <param name=”parametervalues”></param>
/// <returns>新项目的id</returns>
public int insert(params object[] parametervalues)
{
return convert.toint32(base.executescalar(“tt_addproject”,parametervalues));
}
}
}
业务逻辑层代码:(以项目类业务逻辑层代码为例)
/// <summary>
/// 根据用户和用户角色,获取指定用户能够查看的项目列表
/// </summary>
/// <param name=”userid”></param>
/// <param name=”role”></param>
/// <returns></returns>
public static projectscollection getprojects(int userid, string role)
{
string firstname = string.empty;
string lastname = string.empty;
// 创建数据访问层类
dal.project project = new dal.project();
// 调用数据访问层方法
dataset ds = project.getprojects(userid, convert.toint32(role));
projectscollection projects = new projectscollection();
foreach(datarow r in ds.tables[0].rows)
{
project prj = new project();
prj.projectid = convert.toint32(r[“projectid”]);
prj.name = r[“projectname”].tostring();
prj.description = r[“description”].tostring();
prj.manageruserid = convert.toint32(r[“manageruserid”]);
prj.managerusername = ttuser.getdisplayname(convert.tostring(r[“username”]), ref firstname, ref lastname);
prj.estcompletiondate = convert.todatetime(r[“estcompletiondate”]);
prj.estduration = convert.todecimal(r[“estduration”]);
projects.add(prj);
}
return projects;
}