在项目开发的过程中,有时把整个项目分为三层架构,其中包括:表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)。三层的作用分别如下:表示层:为用户提供交互操作界面,这一点不论是对于Web还是WinForm都是如此,就是用户界面操作。我们网站展示给用户看的界面。业务逻辑层:负责关键业务的处理和数据的传递。复杂的逻辑判断和涉及到数据库的数据验证都需要在此做出处理。根据传入的值返回用户想得到的值,或者处理相关的逻辑。数据访问层:见名知意,负责数据库数据的访问。主要为业务逻辑层提供数据,根据传入的值来操作数据库,增、删、改或者其它。以下我简单介绍下一个用户管理模块:为了整个项目的开发方便,我们在项目中会建几个类库SQLHelper,BLL,DAL,Model和一个Web网站。为了命名清晰,我们可以这样命名这个三个工程(即在解决方案里添加的类库):业务逻辑层(BusinessLogicLayer):BLL,命名空间默认设置为BLL数据访问层(DataAccessLayer):DAL,命名空间默认设置为DALSQL帮助类:SQLHelper,命名空间默认设置为SQLHelper另外我们为了数据传递的方便,通常再添加一个类库,这个类库是贯穿于整个三层架构中的。即实体类。通常命名为Model,命名空间默认值设置为:Models。其中封装的每个类都对应一个实体,通常就是数据库中的一个表。如数据库中的用户表(custom)封装为(custom),将表中的每个字段都封装成共有的属性。这样三层架构的搭建就基本完成了。这三层有着非常强的依赖关系:表示层←业务逻辑层←数据访问层他们之间的数据传递是双向的,并且通常借助实体类传递数据。那么三层架构都有哪些优点呢:1、易于项目的修改和维护。在项目的开发过程中或者开发后的升级过程中,甚至在项目的移植过程中。这种三层架构是非常方便的。比如项目从Web移植到Form,我们只需要将表示层重新做一遍就可以了。其余两层不用改动,只需添加到现有项目就可以了。如果不采用这种架构,只是将代码写到表示层。那么所有的编码几乎都要重新来了。2、易于扩展。在功能的扩展上同样如此,如有功能的添加只需把原有的类库添加方法就可了3、易于代码的重用。这一点就不用解释了。4、易于分工协作开还可以加个接口类库Iinterface,加入设计模式,使你的代码灵活性更好,质量更高。下一步讲解数据库的设计。敬请拍砖。要开发用户管理系统,我们首先要了解需求,现在就举一个简单需求,用户表,假设有两种角色用一个字段departID来判断,管理员和员工,我们要先建一个用户表custom和一个部门表department:CREATETABLE[dbo].[custom]([id][int]IDENTITY(1,1)NOTNULL,[cname][nvarchar](50)COLLATEChinese_PRC_CI_ASNOTNULL,[departID][int]NOTNULL,[age][int]NOTNULL,[ename][nvarchar](50)COLLATEChinese_PRC_CI_ASNOTNULL,[password][nvarchar](50)COLLATEChinese_PRC_CI_ASNOTNULL,CONSTRAINT[PK_custom]PRIMARYKEYCLUSTERED([id]ASC)WITH(PAD_INDEX=OFF,STATISTICS_NORECOMPUTE=OFF,IGNORE_DUP_KEY=OFF,ALLOW_ROW_LOCKS=ON,ALLOW_PAGE_LOCKS=ON)ON[PRIMARY])ON[PRIMARY];CREATETABLE[dbo].[department]([id][int]IDENTITY(1,1)NOTNULL,[departname][nvarchar](50)COLLATEChinese_PRC_CI_ASNOTNULL,[description][nchar](10)COLLATEChinese_PRC_CI_ASNOTNULL,CONSTRAINT[PK_department]PRIMARYKEYCLUSTERED([id]ASC)WITH(PAD_INDEX=OFF,STATISTICS_NORECOMPUTE=OFF,IGNORE_DUP_KEY=OFF,ALLOW_ROW_LOCKS=ON,ALLOW_PAGE_LOCKS=ON)ON[PRIMARY])ON[PRIMARY]建完数据库表后,开始写存储过程,插入一条数据:CREATEPROCEDURE[dbo].[spInsertCustom]@cnamenvarchar(50),@enamenvarchar(50),@ageint,@departIDint,@passwordnvarchar(50)ASBEGINinsertintocustom(cname,departID,age,ename,password)values(@cname,@departID,@age,@ename,@password)ENDRETURN@@IdentitycreatePROCEDURE[dbo].[spInsertDepartment]@departnamenvarchar(50),@descriptionnvarchar(50)ASBEGINinsertintodepartment(departname,description)values(@departname,@description)ENDRETURN@@Identity现建两个更新一条数据的存储过程:CREATEPROCEDURE[dbo].[spupdatecustom]@idint,@cnamenvarchar(50),@departIDint,@ageint,@enamenvarchar(50),@passwordnvarchar(50)ASBEGINupdatecustomsetcname=@cname,departID=@departID,age=@age,ename=@ename,password=@passwordwhereid=@idENDCOMMITTRANcreateprocedurespupdatedepart(@departnamenvarchar(50),@descriptionnchar(10),@idint)asUPDATE[dbo].[department]SET[departname]=@departname,[description]=@departnameWHEREid=@id再新建两个取出所有用户的存储过程:CREATEPROCEDURE[dbo].[spGetcustom]ASBEGINselect*fromcustomorderbyiddescENDcreatePROCEDURE[dbo].[spGetAlldepartment]ASBEGINselect*fromdepartmentEND再新建一个根据ID取出一条数据的存储过程:CREATEPROCEDURE[dbo].[spGetcustomer]@idintASBEGINselect*fromcustomwhereid=@idEND现建一个根据部门名取部门ID的存储过程:createPROCEDURE[dbo].[spGetdepartmenter]@departnamenvarchar(50)ASBEGINselect*fromdepartmentwheredepartname=@departnameEND再建两个根据ID删除数据的存储过程:createPROCEDURE[dbo].[spDeletecustom]@idintASBEGINdeletecustomwhereid=@idENDCREATEPROCEDUREspdeletedepart@idintASBEGINdeletedepartmentwhereid=@idENDGO数据库设计就建好了,这只是一个简单的示例.欢迎拍砖.下次讲解SQLHelper的设计.数据库设计好了,我们开始设计SQLHelper了,是一个SQL基类.连接数据源:privateSqlConnectionmyConnection=null;privatereadonlystringRETURNVALUE=RETURNVALUE;打开数据库连接.privatevoidOpen(){//打开数据库连接if(myConnection==null){//myConnection=newSqlConnection(ConfigurationManager.ConnectionStrings[ConnectionString].ConnectionString);myConnection=newSqlConnection(ConfigurationManager.AppSettings[ConnectionString].ToString());}if(myConnection.State==ConnectionState.Closed){try{///打开数据库连接myConnection.Open();}catch(Exceptionex){SystemError.CreateErrorLog(ex.Message);}finally{///关闭已经打开的数据库连接}}}关闭数据库连接publicvoidClose(){///判断连接是否已经创建if(myConnection!=null){///判断连接的状态是否打开if(myConnection.State==ConnectionState.Open){myConnection.Close();}}}释放资源publicvoidDispose(){//确认连接是否已经关闭if(myConnection!=null){myConnection.Dispose();myConnection=null;}}执行无参数和返回int型的存储过程publicintRunProc(stringprocName){SqlCommandcmd=CreateProcCommand(procName,null);try{///执行存储过程cmd.ExecuteNonQuery();}catch(Exceptionex){///记录错误日志SystemError.CreateErrorLog(ex.Message);}finally{///关闭数据库的连接Close();}///返回存储过程的参数值return(int)cmd.Parameters[RETURNVALUE].Value;}执行传入参数和返回int型的存储过程publicintRunProc(stringprocName,SqlParameter[]prams){SqlCommandcmd=CreateProcCommand(procName,prams);try{///执行存储过程cmd.ExecuteNonQuery();}catch(Exceptionex){///记录错误日志SystemError.CreateErrorLog(ex.Message);}finally{///关闭数据库的连接Close();}///返回存储过程的参数值return(int)cmd.Parameters[RETURNVALUE].Value;}执行存储过程和返回SqlDataReaderpublicvoidRunProc(stringprocName,outSqlDataReaderdataReader){///创建CommandSqlCommandcmd=CreateProcCommand(procName,null);try{///读取数据dataReader=cmd.ExecuteReader(CommandBehavior.Clos