一般来说,对系统的分层,一般都需要下面几个层:实体层(Entity)、数据访问层(DAL)、业务逻辑层(BLL)、界面层(UI);而数据访问层,一般也会加入一个接口层(IDAL)。
在其中的实体层,一般是根据数据库进行映射外加入注释等,技术含量不大,在此一笔带过;数据库访问层和业务逻辑层,是关键之所在,因为这里好的设计,会利用很多基类的操作,减少很多代码和重复劳动;界面层,不管是WebForm还是WinForm,都是尽可能少的逻辑代码或者SQL语句在其中,好的项目可能会利用一些优秀的控件进去,提高体验,减少代码。另外,由于一些创建操作费时费资源,一般还需要把可重复利用的资源缓存起来,提高性能。
先给大家预览下项目的框架,再一层层分析讨论:

1、 实体层(定义一个空的基类,其他实体类继承之,主要是为了利用泛型操作,用途下面细说)
public class BaseEntity

{
}
public class EquipmentInfo : BaseEntity

{

Field Members#region Field Members

private int m_ID = 0; //ID
private string m_PartID = ""; //备件编号
//



#endregion


Property Members#region Property Members

/**//// <summary>
/// ID
/// </summary>
public virtual int ID

{
get

{
return this.m_ID;
}
set

{
this.m_ID = value;
}
}


/**//// <summary>
/// 备件编号
/// </summary>
public virtual string PartID

{
get

{
return this.m_PartID;
}
set

{
this.m_PartID = value;
}
}

//



#endregion

}
2、 数据库访问层,数据访问层的关键是数据访问基类的设计,基类实现大多数数据库的日常操作,如下:

/**//// <summary>
/// 数据访问层的基类
/// </summary>
public abstract class BaseDAL<T> : IBaseDAL<T> where T : BaseEntity, new()

{
}
BaseEntity就是实体类的基类,IBaseDAL是定义的数据访问基类接口,包含各种常用的操作定义;因此BaseDAL就是要对各种操作的进行实现,实现接口越多,将来继承类的重用程度就越高。
以上通过泛型<T> ,我们就可以知道实例化那个具体访问类的信息了,可以实现强类型的函数定义。

/**//// <summary>
/// 一些基本的,作为辅助函数的接口
/// </summary>
public interface IBaseDAL<T> where T : BaseEntity

{

/**//// <summary>
/// 查询数据库,检查是否存在指定键值的对象
/// </summary>
/// <param name="recordTable">Hashtable:键[key]为字段名;值[value]为字段对应的值</param>
/// <returns>存在则返回<c>true</c>,否则为<c>false</c>。</returns>
bool IsExistKey(Hashtable recordTable);


/**//// <summary>
/// 查询数据库,检查是否存在指定键值的对象
/// </summary>
/// <param name="fieldName">指定的属性名</param>
/// <param name="key">指定的值</param>
/// <returns>存在则返回<c>true</c>,否则为<c>false</c>。</returns>
bool IsExistKey(string fieldName, object key);


/**//// <summary>
/// 获取数据库中该对象的最大ID值
/// </summary>
/// <returns>最大ID值</returns>
int GetMaxID();


/**//// <summary>
/// 根据指定对象的ID,从数据库中删除指定对象
/// </summary>
/// <param name="key">指定对象的ID</param>
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns>
bool DeleteByKey(string key);

/**//// <summary>
/// 根据条件,从数据库中删除指定对象
/// </summary>
/// <param name="condition">删除记录的条件语句</param>
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns>
bool DeleteByCondition(string condition);



/**//// <summary>
/// 插入指定对象到数据库中
/// </summary>
/// <param name="obj">指定的对象</param>
/// <returns>执行成功返回True</returns>
bool Insert(T obj);


/**//// <summary>
/// 更新对象属性到数据库中
/// </summary>
/// <param name="obj">指定的对象</param>
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns>
bool Update(T obj, string primaryKeyValue);


/**//// <summary>
/// 查询数据库,检查是否存在指定ID的对象(用于整型主键)
/// </summary>
/// <param name="key">对象的ID值</param>
/// <returns>存在则返回指定的对象,否则返回Null</returns>
T FindByID(int key);


/**//// <summary>
/// 查询数据库,检查是否存在指定ID的对象(用于字符型主键)
/// </summary>
/// <param name="key">对象的ID值</param>
/// <returns>存在则返回指定的对象,否则返回Null</returns>
T FindByID(string key);


返回集合的接口#region 返回集合的接口


/**//// <summary>
/// 根据ID字符串(逗号分隔)获取对象列表
/// </summary>
/// <param name="idString">ID字符串(逗号分隔)</param>
/// <returns>符合条件的对象列表</returns>
List<T> FindByIDs(string idString);


/**//// <summary>
/// 根据条件查询数据库,并返回对象集合
/// </summary>
/// <param name="condition">查询的条件</param>
/// <returns>指定对象的集合</returns>
List<T> Find(string condition);


/**//// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <returns>指定对象的集合</returns>
List<T> Find(string condition, PagerInfo info);


/**//// <summary>
/// 返回数据库所有的对象集合
/// </summary>
/// <returns>指定对象的集合</returns>
List<T> GetAll();


/**//// <summary>
/// 返回数据库所有的对象集合(用于分页数据显示)
/// </summary>
/// <param name="info">分页实体信息</param>
/// <returns>指定对象的集合</returns>
List<T> GetAll(PagerInfo info);

DataSet GetAllToDataSet(PagerInfo info);

#endregion
}
细看上面代码,会发现由一个PagerInfo 的类,这个类是用来做分页参数传递作用的,根据这个参数,你可以知道具体返回那些关心的记录信息,这些记录又转换为强类型的List<T>集合。
再看看数据库访问基类的具体实现代码吧:

/**//// <summary>
/// 数据访问层的基类
/// </summary>
public abstract class BaseDAL<T> : IBaseDAL<T> where T : BaseEntity, new()

{

构造函数#region 构造函数

protected string tableName;//需要初始化的对象表名
protected string primaryKey;//数据库的主键字段名
protected string sortField = "LastUpdated";//排序字段
private bool isDescending = true;//

/**//// <summary>
/// 排序字段
/// </summary>
public string SortField

{
get

{
return sortField;
}
set

{
sortField = value;
}
}


/**//// <summary>
/// 是否为降序
/// </summary>
public bool IsDescending

{

get
{ return isDescending; }

set
{ isDescending = value; }
}


/**//// <summary>
/// 数据库访问对象的表名
/// </summary>
public string TableName

{
get

{
return tableName;
}
}


/**//// <summary>
/// 数据库访问对象的外键约束
/// </summary>
public string PrimaryKey

{
get

{
return primaryKey;
}
}
public BaseDAL()

{}


/**//// <summary>
/// 指定表名以及主键,对基类进构造
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="primaryKey">表主键</param>
public BaseDAL(string tableName, string primaryKey)

{
this.tableName = tableName;
this.primaryKey = primaryKey;
}

#endregion


通用操作方法#region 通用操作方法


/**//// <summary>
/// 添加记录
/// </summary>
/// <param name="recordField">Hashtable:键[key]为字段名;值[value]为字段对应的值</param>
/// <param name="trans">事务对象,如果使用事务,传入事务对象,否则为Null不使用事务</param>
public bool Insert(Hashtable recordField, DbTransaction trans)

{
return this