一般来说,对系统的分层,一般都需要下面几个层:实体层(Entity)、数据访问层(DAL)、业务逻辑层(BLL)、界面层(UI);而数据访问层,一般也会加入一个接口层(IDAL)。
在其中的实体层,一般是根据数据库进行映射外加入注释等,技术含量不大,在此一笔带过;数据库访问层和业务逻辑层,是关键之所在,因为这里好的设计,会利用很多基类的操作,减少很多代码和重复劳动;界面层,不管是WebForm还是WinForm,都是尽可能少的逻辑代码或者SQL语句在其中,好的项目可能会利用一些优秀的控件进去,提高体验,减少代码。另外,由于一些创建操作费时费资源,一般还需要把可重复利用的资源缓存起来,提高性能。
先给大家预览下项目的框架,再一层层分析讨论:
1、 实体层(定义一个空的基类,其他实体类继承之,主要是为了利用泛型操作,用途下面细说)
publicclassBaseEntity
{
}
publicclassEquipmentInfo : BaseEntity
{
Field Members#regionField Members
privateintm_ID =0;//ID
privatestringm_PartID ="";//备件编号
//
#endregion
Property Members#regionProperty Members
/**///ID
///
publicvirtualintID
{
get
{
returnthis.m_ID;
}set
{
this.m_ID = value;
} }
/**///备件编号
///
publicvirtualstringPartID
{
get
{
returnthis.m_PartID;
}set
{
this.m_PartID = value;
} }
//
#endregion
}
2、 数据库访问层,数据访问层的关键是数据访问基类的设计,基类实现大多数数据库的日常操作,如下:
/**///数据访问层的基类
///
publicabstractclassBaseDAL : IBaseDALwhereT : BaseEntity,new()
{
}
BaseEntity就是实体类的基类,IBaseDAL是定义的数据访问基类接口,包含各种常用的操作定义;因此BaseDAL就是要对各种操作的进行实现,实现接口越多,将来继承类的重用程度就越高。
以上通过泛型 ,我们就可以知道实例化那个具体访问类的信息了,可以实现强类型的函数定义。
/**///一些基本的,作为辅助函数的接口
///
publicinterfaceIBaseDALwhereT : BaseEntity
{
/**///查询数据库,检查是否存在指定键值的对象
//////Hashtable:键[key]为字段名;值[value]为字段对应的值///存在则返回true,否则为false。
boolIsExistKey(Hashtable recordTable);
/**///查询数据库,检查是否存在指定键值的对象
//////指定的属性名///指定的值///存在则返回true,否则为false。
boolIsExistKey(stringfieldName,objectkey);
/**///获取数据库中该对象的最大ID值
//////最大ID值
intGetMaxID();
/**///根据指定对象的ID,从数据库中删除指定对象
//////指定对象的ID///执行成功返回true,否则为false。
boolDeleteByKey(stringkey);
/**///根据条件,从数据库中删除指定对象
//////删除记录的条件语句///执行成功返回true,否则为false。
boolDeleteByCondition(stringcondition);
/**///插入指定对象到数据库中
//////指定的对象///执行成功返回True
boolInsert(T obj);
/**///更新对象属性到数据库中
//////指定的对象///执行成功返回true,否则为false。
boolUpdate(T obj,stringprimaryKeyValue);
/**///查询数据库,检查是否存在指定ID的对象(用于整型主键)
//////对象的ID值///存在则返回指定的对象,否则返回Null
T FindByID(intkey);
/**///查询数据库,检查是否存在指定ID的对象(用于字符型主键)
//////对象的ID值///存在则返回指定的对象,否则返回Null
T FindByID(stringkey);
返回集合的接口#region返回集合的接口
/**///根据ID字符串(逗号分隔)获取对象列表
//////ID字符串(逗号分隔)///符合条件的对象列表
List FindByIDs(stringidString);
/**///根据条件查询数据库,并返回对象集合
//////查询的条件///指定对象的集合
List Find(stringcondition);
/**///根据条件查询数据库,并返回对象集合(用于分页数据显示)
//////查询的条件///分页实体///指定对象的集合
List Find(stringcondition, PagerInfo info);
/**///返回数据库所有的对象集合
//////指定对象的集合
List GetAll();
/**///返回数据库所有的对象集合(用于分页数据显示)
//////分页实体信息///指定对象的集合
List GetAll(PagerInfo info);
DataSet GetAllToDataSet(PagerInfo info);
#endregion }
细看上面代码,会发现由一个PagerInfo 的类,这个类是用来做分页参数传递作用的,根据这个参数,你可以知道具体返回那些关心的记录信息,这些记录又转换为强类型的List集合。
再看看数据库访问基类的具体实现代码吧:
/**///数据访问层的基类
///
publicabstractclassBaseDAL : IBaseDALwhereT : BaseEntity,new()
{
构造函数#region构造函数
protectedstringtableName;//需要初始化的对象表名
protectedstringprimaryKey;//数据库的主键字段名
protectedstringsortField ="LastUpdated";//排序字段
privateboolisDescending =true;//
/**///排序字段
///
publicstringSortField
{
get
{
returnsortField;
}set
{
sortField = value;
} }
/**///是否为降序
///
publicboolIsDescending
{
get{returnisDescending; }
set{ isDescending = value; } }
/**///数据库访问对象的表名
///
publicstringTableName
{
get
{
returntableName;
} }
/**///数据库访问对象的外键约束
///
publicstringPrimaryKey
{
get
{
returnprimaryKey;
} }
publicBaseDAL()
{}
/**///指定表名以及主键,对基类进构造
//////表名///表主键
publicBaseDAL(stringtableName,stringprimaryKey)
{
this.tableName = tableName;
this.primaryKey = primaryKey;
}
#endregion
通用操作方法#region通用操作方法
/**///添加记录
//////Hashtable:键[key]为字段名;值[value]为字段对应的值///事务对象,如果使用事务,传入事务对象,否则为Null不使用事务
publicboolInsert(Hashtable recordField, DbTransaction trans)
{
returnthis.Insert(recordField, tableName, trans);
}
/**///添加记录
//////Hashtable:键[key]为字段名;值[value]为字段对应的值///需要操作的目标表名称///事务对象,如果使用事务,传入事务对象,否则为Null不使用事务