- 1.84 MB
- 2022-05-17 13:37:04 发布
- 1、本文档共5页,可阅读全部内容。
- 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
- 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
- 文档侵权举报电话:19940600175。
学生晚归与考勤管理信息系统开发系统分析及设计3.1系统预期用户本系统的预期用户是任何想了解学生在校的考勤情况的用户。3.2功能说明学生晚归与考勤管理系统是目前广西机电职业技术校园网在线系统之一。本软件将各个学院各个部门联系到一起,便于学生晚归、考勤的管理,同时,还可以让学生通过查询自己的晚归与考勤记录,了解到自己的纪律情况。在线图书销售系统要实现的功能模块主要有:该系统分为晚归情况管理、考勤情况管理与后台管理三大功能模块。系统功能模块的划分图1系统功能架构图(2)基本处理流程下图是系统基本处理流程图。
图2系统基本处理流程3.3数据库设计本系统采用SQLServer2005作为后台数据库。根据以上功能,新建一名为Attendance的数据库,其中共包括9个数据表,分别是部门表(department):专业信息表(special):班级信息表(class):
学生信息表(stuInfo):区/门信息表(region):晚归情况表(late):考勤情况表(attendance):
考勤类型表(attendtype):用户信息表(admin):各个数据表的关系(主要是主键与外键的约束关系)如下图所示:
数据库创建脚本参考文件:“学生晚归与考勤管理信息系统数据库建库脚步.sql”3.4数据库连接1、建议将数据库拷入网站内的App_Data目录内,然后将数据库连接字符串写入到Web.config,参考代码如下: 测试数据库连接是否正常usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Data.SqlClient;publicpartialclassDBConnTest:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){stringconstr=ConfigurationManager.AppSettings["ConnectionStr"];SqlConnectionconn=newSqlConnection(constr);conn.Open();//打开数据库连接Response.Write("数据库连接成功!");conn.Close();//关闭数据库连接Response.Write("数据库关闭成功!");}}经验证,Attendance.mdf数据库连接正常2、将常用数据库操作代码写入公共类DB中,其中包含以下各自定义方法,参考代码如下:usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Data.SqlClient;//////DB类为一个专门进行数据库操作的类///包括连接数据库,更新数据库,查询数据库这些操作/// publicclassDB{//////DB()为DB类的构造方法/// publicDB(){
}//////定义返回数据库连接对象SqlConnection方法/// //////SqlConnection对象/// publicSqlConnectiongetCon(){StringstrCon=ConfigurationManager.AppSettings["ConnectionStr"];//从配置文件web.cofig里面读取数据库的连接字符串returnnewSqlConnection(strCon);//返回数据库连接对象}//////定义更新数据库的方法/// //////参数cmdStr为要执行更新数据库的SQL语句,包含增加,修改,删除这三种SQL语句/////////数据库更新成功则返回1,更新失败则返回0/// publicintsqlEx(stringcmdStr){SqlConnectioncon=getCon();con.Open();//打开数据库连接SqlCommandcmd=newSqlCommand(cmdStr,con);//创建执行SQL语句的命令对象SqlCommandtry{cmd.ExecuteNonQuery();return1;//成功返回1}catch{return0;//失败返回0}finally{con.Dispose();//释放资源}
}//////定义查询数据库信息的方法/// //////参数cmdStr为执行查询时的书写的SQL语句////// publicDataTablereDt(stringcmdStr){SqlConnectioncon=getCon();//连接数据库con.Open();SqlDataAdapterda=newSqlDataAdapter(cmdStr,con);//创建数据适配器对象DataSetds=newDataSet();//创建数据集对象da.Fill(ds);//将保存在数据适配器对象中的数据填充到数据集对象中return(ds.Tables[0]);//返回数据集对象中有记录的那个表}//////定义阅读数据的方法/// //////参数str为执行查询操作时的SQL语句/////////返回一个数据阅读对象/// publicSqlDataReaderreDr(stringstr){SqlConnectioncon=getCon();con.Open();SqlCommandcmd=newSqlCommand(str,con);SqlDataReaderdr=cmd.ExecuteReader(CommandBehavior.CloseConnection);//通过调用Command对象的ExecuteReader()方法创建DataReader对象,CommandBehavior.CloseConnection表示?returndr;}}功能模块的实现用户注册功能的实现:
实现逻辑:用户注册信息写入到admin表,此注册功能是专门针对本校的学生开发注册的,如果不是本校的学生,是没有注册的权限的,所有注册时要根据学生输入的真实姓名和学号进行注册,如果找不到对应的学生的名字,就不允许用户进行注册,如果用户已经注册过一次了,就直接告诉用户已经注册过了,无需再次注册了,并自动为用户跳转到登录页面,如果用户是第一次注册,就把用户的注册信息写入到admin表中,注册成功后也跳转到登录页面让用户进行登录。用户注册页面Register.aspx如下图所示:学生进入此页面进行注册,正确填写了学生姓名和学生学号以及验证码了以后,点击提交按钮完成帐户注册,而在后台,要进行数据的合法性判断,首先进行的是验证码的正确性判断,把用户输入的验证码和保存的Session对象中的验证码取出来作比较,如果验证码输入正确才继续执行检查该注册用户是否是本校的学生,以及该用户是否已经被注册了,后台的处理代码如下所示:Register.aspx.csusingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Data.SqlClient;publicpartialclassstudent_Register:System.Web.UI.Page
{DBdb=newDB();protectedvoidPage_Load(objectsender,EventArgse){this.ImageButton1.ImageUrl="image.aspx";//image.aspx是一个显示验证码的Web页面}protectedvoidbtn_submit_Click(objectsender,EventArgse){stringcode=txtCheckCode.Text.Trim();if(code!=(string)Session["image"]){Response.Write("");//Response.Redirect("Register.aspx");如果使用这种跳转方式,那么上面的javascript是无法运行的,因为还没有来得及运行就页面就已经跳转了Response.Write("");}else{stringstu_Name=txtUserName.Text.Trim();stringstu_Id=txtstuID.Text.Trim();stringsql2="selectstu_namefromstuInfowherestu_name=""+stu_Name+""";//使用这条SQL语句检查要注册的人是否是本校的学生,如果是,才允许其注册,如果不是,就不允许其注册SqlDataReaderdr=db.reDr(sql2);if(dr.Read()){dr.Close();//关闭SqlDataReaderstringsq="select*fromadminwherelogin_name=""+stu_Name+""";//如果已经证实是本校的学生,就再判断该学生是否已经注册过了dr=db.reDr(sq);//再次使用SqlDataReaderif(dr.Read()){Response.Write("");Response.Write("");}else{intpower=3;//如果已经证实要注册的人是本校的学生,就直接给该学生赋予使用权限stringsql="insertintoadmin(login_name,login_pwd,admin_power)values(""+stu_Name+"",""+stu_Id+"","+power+")";//Response.Write(sql);//Response.End();
try{intflag=db.sqlEx(sql);if(flag>0){Response.Write("");Response.Write("");}else{Response.Write("");}}catch(System.Exceptionee){Response.Write("");}}}else{Response.Write("");txtUserName.Text="";txtstuID.Text="";}}}protectedvoidbtn_reset_Click(objectsender,EventArgse){txtstuID.Text="";txtUserName.Text="";}}用户登录功能的实现实现逻辑:用户进入登录页面后,输入相关的用户名和密码进行登录,如果用户名和密码都正确了,表示该用户是合法用户,就允许其进入系统的主页进行相关的系统操作,如果用户名和密码的验证不通过,就不允许其进入系统,用户输入用户名和密码后,在后台的处理过程中首先会从数据库Attendance.mdf
的admin表取出相应的用户名和用户输入的用户名进行匹配,如果用户名匹配成功了,就把数据表中存储的密码和用户输入的密码进行比对,如果密码也验证通过了,才允许用户进入系统首页,用户名和密码中任意一项匹配如果不通过,都不允许其登录。登录该系统时,有三种不同身份的使用者,分别为管理员,记录员和学生,不同的身份就对应着不同的使用权限。使用权限的限制根据不同身份的登录者生成不同的动态导航,以此到达限定使用者的权限的目的。登录页面的设计如下:如果登录的身份是管理员,则显示如下的导航:如果登录的身份是记录员,则显示如下的导航:如果登录的身份是学生,则显示如下的导航:
对于管理员而言,其拥有的使用权限是最多的,但没有晚归登记和考勤登记的权限,登记权限只有记录员才有,而对于学生而言,只有查看相关记录的权限,别的权限都没有,因此通过这种根据不同登录者的身份生成不同的导航就可以限定了登录者的使用权限了。这里难就难在了如果根据登录者的身份动态生成不同的导航信息。相关代码如下:用户登录的后台代码:login.aspx.csusingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Data.SqlClient;publicpartialclasslogin:System.Web.UI.Page{DBdb=newDB();protectedvoidPage_Load(objectsender,EventArgse){ImageButton1.ImageUrl="image.aspx";//让页面加载时就显示验证码图片}protectedvoidbtnRegister_Click(objectsender,EventArgse){Response.Redirect("Register.aspx");//点击注册按钮后,直接跳转到注册页面,这里需要注意一个小问题,由于文本框已经使用了验证控件,因此要想让按钮的触发事件不触发验证控件时,把按钮的CausesValidation属性设置为false即可}protectedvoidbtnLogin_Click(objectsender,EventArgse)
{stringcode=txtCheckCode.Text.Trim();//获取输入的验证码stringusername=txtUserName.Text.Trim();//获取输入的用户名stringpassword=txtPassword.Text.Trim();//获取输入的密码if(code!=(string)Session["image"])//先进行验证码的判断,验证码输入正确后在执行其他的操作{Response.Write("");Response.Write("");}else{stringsql="selectlogin_name,login_pwd,admin_powerfromadminwherelogin_name=""+username+""";SqlDataReaderdr=db.reDr(sql);if(dr.Read()){if((string)dr["login_pwd"]==password){Response.Write("");Response.Write("");Session["Power"]=dr["admin_power"];//使用Session存储用户的使用权限Session["username"]=username;//存储用户名}else{Response.Write("");Response.Write("");}}else{Response.Write("");Response.Write("");}}}}
在用户进行登录的时候,使用Session对象存储用户名,并且根据用户名从数据库中取出该用户的使用权限,也使用Session对象保存用户的使用权限,登录成功后,在系统的主页的后台处理代码中取出保存在Session对象中的用户名的相关的用户权限,然后根据用户权限来动态生成导航,相关的代码如下:系统主页的后台处理代码:index.aspx.csusingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;publicpartialclassIndex:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){if(Session["username"]!=null)//这里使用Session对象对用户是否已经进行登录进行判断,如果Session中的内容不为空,则表示用户已经登录{stringuserStr=(string)Session["username"];//取出保存在Session对象中的用户名intpower=int.Parse(Session["Power"].ToString());//取出保存在Session对象中的用户使用权限标识stringnav="";if(power==1)//根据登录者的身份动态变化导航的显示,以此限定不同身份的登录者的使用权限{nav="晚归查询| ";nav+="晚归汇总| ";nav+="考勤查询| ";nav+="考勤汇总| ";nav+="系/班级/专业维护| ";nav+="区/门维护| ";nav+="用户管理| ";nav+="注销用户 ";}elseif(power==2){
nav="晚归查询| ";nav+="晚归汇总| ";nav+="晚归登记| ";nav+="考勤查询| ";nav+="考勤汇总| ";nav+="考勤登记| ";nav+="注销用户 ";}elseif(power==3){nav="晚归查询| ";nav+="晚归汇总| ";nav+="考勤查询| ";nav+="考勤汇总| ";nav+="注销用户 ";}lblNav.Text="
";lblNav.Text+="欢迎"+userStr+"登录";}else{//如果用户没有进行登录,则直接跳转到登录页面Response.Write("");Response.Write("");}//Response.Write("");向网页中输出一个框架lblContent.Text="";//让框架在指定的Lable中显示}}到此,用户注册和登录的功能模块就全部实现了接下来将进入系统开发中的最核心的功能模块部分的开发:晚归情况管理和考勤情况管理,这两个部分是系统功能中最核心的两个部分,也是最难实现的两个部分,这两个部分难就难在了查询的部分,如何根据用户的选择查询操作动态拼凑出SQL语句对数据库进行操作,从而查询出用户想要的记录。晚归情况管理功能模块的实现
晚归情况管理功能模块主要有三部分,分别为晚归登记,晚归查询,晚归汇总。如下图所示:晚归情况管理晚归登记晚归查询晚归汇总实现晚归登记功能latewrite.aspx页面设计如下:在数据库的设计中,存储晚归情况的表为late表,late表的设计如下图所示:
从表中可以看到,late表存储的信息为学生的学号(stu_id)、区/门编号(region_id)以及晚归时间(late_time)和晚归事由(late_intro)。记录员在进行晚归情况记录时,首先要选择的系部,专业,班级,区/门,姓名这些相关的学生的信息,然后写上晚归时间和晚归事由后,点击【记录】按钮,完成晚归情况的登记。这里需要注意的地方是,记录员选择的系部名称,专业名称,班级名称以及学生名称这些信息是早就已经随着数据库的创建插入到相关的表中存放了,因此没有必要再次把这些重复的信息写入到数据库中,而且从存储晚归情况记录的late表中也可以看出,late表并没有定义有可以存储系部,专业,班级、区/门和姓名的字段,但可以看到,late表中存放有学生的学号(stu_id),区门的编号(region_id),当初进行数据库设计时,就已经定义了late表中的stu_id(外键)字段和stuInfo表的stu_id(主键)字段之间的约束关系,因此可以通过late表的stu_id找到stuInfo表中对应着的stu_id所表示的学生,而stuInfo表的设计如下图所示:从学生信息表(stuInfo)的定义中可以看出,学生信息表中存放有系部的编号(dept_id)、专业编号(spc_id)以及(class_id),这三个字段都作为外键与相应的department表的dept_id(主键)、spcieal表的spc_id(主键)以及class表的class_id(主键)建立起主键外键的约束关系,因此通过stuInfo表就可以找到与该晚归学生相关的系部,专业以及所在的班级,这样有关该晚归学生的全部信息就可以通过多表联合查询从stuInfo表(得到学生姓名),class表(得到班级),spceial表(得到专业)和department表(得到系部)得到。这就是建立起主键外键约束的好处,可以把表和表通过某种关系关联起来,使之成为有一定依赖关系的表,从而保持了数据的完整性。晚归情况记录表(late)中的region_id记录了学生晚归的区/门编号,通过该编号就可以找到存放在region表中对应的区/门信息。做这个功能模块时,容易产生一个误区,会很自然地认为记录员选择的系部,专业,班级,姓名,区/门以及填写的晚归时间和晚归事由这些有关晚归的信息全部都要写入到数据库里面,如果这样想,那么这个功能模块就没有办法做了,而且会越做越复杂,会产生很多重复的数据,可能有的人会想到再创建一个表,专门用来存放这些信息,其实是完全没有必要这样做的。使用一个late表存放晚归情况记录即已经可以了。
其它的系部,班级,专业等相关信息在别的表已经存放有了,因此没有必要再次把这些信息写入到数据库中存放,造成数据的冗余以及存储空间的浪费。latewrite.aspx.cs相关的代码如下:usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Data.SqlClient;publicpartialclasslatewrite:System.Web.UI.Page{DBdb=newDB();protectedvoidPage_Load(objectsender,EventArgse){if(!IsPostBack){stringsql="selectdept_id,dept_namefromdepartment";SqlDataReaderdr=db.reDr(sql);//获取数据源,数据源来源于department表dp_dept.DataSource=dr;//绑定数据源到dp_selectDept中dp_dept.DataValueField="dept_id";//给DropDownList1的下拉列表的项赋值dp_dept.DataTextField="dept_name";//显示给用户看的文本dp_dept.DataBind();//显示数据dp_dept.Items.Insert(0,newListItem("==请选择系部==",""));//在第0个位置插入一个下拉项,显示的DataTextField为"==请选择系部==",下拉项的DataValueField为空dp_spc.Items.Insert(0,newListItem("==请选择专业==",""));dp_class.Items.Insert(0,newListItem("==请选择班级==",""));dp_name.Items.Insert(0,newListItem("==请选择姓名=="));sql="selectregion_id,region_namefromregion";dr=db.reDr(sql);dp_region.DataSource=dr;dp_region.DataValueField="region_id";dp_region.DataTextField="region_name";dp_region.DataBind();dp_region.Items.Insert(0,newListItem("==请选择区/门==",""));}}protectedvoiddp_dept_SelectedIndexChanged(objectsender,EventArgse)
{stringdept_id=dp_dept.SelectedValue;//获取中选定的项的value,SelectedValue的意思很明显,意思为选中的值//注意:这里的判断不要写成if(dept_id!=null)这样写会出错的if(dept_id!="")//这里要进行判断,如果选中的是第一项,即显示文本为“==请选择系部==”这一项时,dept_id是没有值的,即为空{stringsql="selectspc_id,spc_namefromspecialwheredept_id="+dept_id;//查询出与dept_id相等的记录,这里的dept_id为整型,所以不用加单引号引起来SqlDataReaderdr=db.reDr(sql);//获取数据源,数据源来源于special表dp_spc.DataSource=dr;//绑定数据源dp_spc.DataTextField="spc_name";//显示专业名称给用户看dp_spc.DataValueField="spc_id";//把专业的id值赋值给下拉列表的项dp_spc.DataBind();//显示数据dp_spc.Items.Insert(0,newListItem("==请选择专业==",""));}else{//如果dp_dept选中的是第一项“==请选择系部==”,此时的DataValueField是为空的,所以要相应的把dp_spc,dp_class,dp_name中的项清空掉dp_spc.Items.Clear();//清空DropDownList2下拉列表的项dp_spc.Items.Insert(0,newListItem("==请选择专业==",""));dp_class.Items.Clear();//清空DropDownList3下拉列表的项dp_class.Items.Insert(0,newListItem("==请选择班级==",""));dp_name.Items.Clear();//清空下拉列表的项dp_name.Items.Insert(0,newListItem("==请选择姓名==",""));}}protectedvoiddp_spc_SelectedIndexChanged(objectsender,EventArgse){stringspc_id=dp_spc.SelectedValue;if(spc_id!=""){stringsql="selectclass_id,class_namefromclasswherespc_id="+spc_id;SqlDataReaderdr=db.reDr(sql);//获取数据源,数据源来源于class表dp_class.DataSource=dr;//绑定数据源到dp_class.DataTextField="class_name";dp_class.DataValueField="class_id";dp_class.DataBind();dp_class.Items.Insert(0,newListItem("==请选择班级==",""));}else
{dp_class.Items.Clear();dp_class.Items.Insert(0,newListItem("==请选择班级=="));}}protectedvoiddp_class_SelectedIndexChanged(objectsender,EventArgse){stringclass_id=dp_class.SelectedValue;if(class_id!=""){stringsql="selectstu_id,stu_namefromstuInfowhereclass_id="+class_id;SqlDataReaderdr=db.reDr(sql);//获取数据源,数据源来源于stuInfo表dp_name.DataSource=dr;//绑定数据源dp_name.DataTextField="stu_name";dp_name.DataValueField="stu_id";dp_name.DataBind();dp_name.Items.Insert(0,newListItem("==请选择姓名==",""));}else{dp_name.Items.Clear();//清空下拉列表的项dp_name.Items.Insert(0,newListItem("==请选择姓名==",""));}}protectedvoidbtn_record_Click(objectsender,EventArgse){DateTimelateTime=DateTime.Parse(txtLateTime.Text.Trim());//获取从文本框输入的晚归时间字符串,并把字符串转换成真正的时间类型stringlateIntro=txtContent.Text.Trim();//获取输入的晚归事由,Trim()方法的作用是截断字符串左右两边的空格stringstuId=dp_name.SelectedValue;//从选中的dp_name的项的value获取到stu_idstringregionId=dp_region.SelectedValue;//从选中的dp_region的项的value获取到region_idstringsql="insertintolate(stu_id,region_id,late_time,late_intro)values(""+stuId+"","+regionId+",""+lateTime+"",""+lateIntro+"")";
try{intflag=db.sqlEx(sql);if(flag>0){Response.Write("");txtContent.Text="";txtLateTime.Text="";}else{Response.Write("");}}catch(System.Exceptionee){Response.Write("");}}protectedvoidbtn_reset_Click(objectsender,EventArgse){txtContent.Text="";txtLateTime.Text="";}}到此,实现晚归情况记录功能。实现晚归查询功能模块latecheck.aspx的页面设计如下:
这个模块最难就难在如何根据用户选择的查询条件动态地组合SQL查询语句,这里使用一个GridView控件用于显示用户查询后的数据。这里的查询逻辑是这样的:如果用户进入此查询页面查询数据时,当用户直接单击查询按钮,不选择任何的查询条件,就将全部信息绑定到GridView中显示出来,如果用户查询时加上了查询条件(如:用户可以选择系部进行查询,或者是选择系部和专业作为查询条件进行查询,或者是选择系部,专业和班级进行作为查询条件进行查询,或者直接输入要查询的姓名或者宿舍或者开始时间或者是结束时间或者是同时输入这些查询关键字或者是输入查询关键字的同时由选择了系部,专业和班级等关键词组成的查询条件),那么就根据查询条件从数据库中查询出满足条件的记录,将满足的记录绑定到GridView控件中进行输出显示。查询部分的代码如下:protectedvoidbtnSearch_Click(objectsender,EventArgse){stringsql="selectstuInfo.stu_name,stuInfo.room,class.class_name,region.region_name,late.late_intro,late.late_time,late.late_idfromstuInfo,class,region,latewherestuInfo.class_id=class.class_idandstuInfo.stu_id=late.stu_idandregion.region_id=late.region_id";/*如果用户没有选择查询条件,只是单击查询按钮,就只执行这条SQL
语句,将全部的记录查询出来*/stringdept_Id=dp_selectDept.SelectedValue;stringspc_Id=dp_selectSpec.SelectedValue;stringclass_Id=dp_selectClass.SelectedValue;stringregion_Id=dp_selectRegion.SelectedValue;stringstartime=txtStartTime.Text;stringendtime=txtEndTime.Text;stringroom=txtRoom.Text;stringname=txtName.Text;if(dept_Id!=""){//如果用户选择了系部,则重新组合SQL语句,加上查询条件——“系部编号”sql+="andstuInfo.dept_id="+dept_Id;}if(spc_Id!=""){//如果用户选择了专业sql+="andstuInfo.spc_id="+spc_Id;}if(class_Id!=""){//如果用户选择了班级sql+="andstuInfo.class_id="+class_Id;}if(region_Id!=""){//如果用户选择了专门sql+="andlate.region_id="+region_Id;}if(startime!=""&&endtime==""){//如果用户只输入了开始时间,结束时间为空//sql+="andlate.late_time=""+startime+""";sql+="andlate.late_timelike"%"+startime+"%"";//遗留的问题,如何对时间进行模糊查询}if(endtime!=""&&startime==""){//如果用户只输入了结束时间,开始时间为空sql+="andlate.late_time=""+endtime+""";}if(startime!=""&&endtime!=""){//如果用户同时输入了结束时间和开始时间sql+="andlate.late_timebetween""+startime+""and""+endtime+""";}if(room!=""){//如果用户输入了宿舍关键字sql+="andstuInfo.roomlike"%"+room+"%"";//进行模糊查询,使查询更加人性化,用户只需要输入有关宿舍一个关键字就可以找到与关键字相关的记录
}if(name!=""){//如果用户只输入了姓名关键字sql+="andstuInfo.stu_namelike"%"+name+"%"";//进行模糊查询,使查询更加人性化,用户只需要输入姓名中的一个关键字就可以找到与关键字相关的记录}//Response.Write(sql);//调试语句,用于调试SQL语句是否正常//Response.End();//程序执行到这里以后就不再往下执行了DataTabledt=db.reDt(sql);GridView_DataShow.DataSource=dt;//绑定数据源到GridView_DataShowGridView_DataShow.DataBind();//显示数据}这里的多表联合查询涉及到的表有stuInfo,class,region,late这四个表,组合查询条件“wherestuInfo.class_id=class.class_idandstuInfo.stu_id=late.stu_idandregion.region_id=late.region_id”都是根据各个表之间建立的主键外键约束关系建立起来的。这条语句难就难在如何找出各个表之间的联系,继而组合出查询条件,以及后面根据用户进行的查询条件的选择动态地添加查询条件,重新拼凑SQL语句进行查询。运行结果如下图所示:当用户什么条件都没有选择就直接点击【查询】按钮时,显示出全部的查询信息当用户查询出了想要的信息以后,点击【查看】这个超链接,就可以跳转到lateview.aspx页面显示指定学生的详细信息,如下图lateview.aspx页面设计如下所示:
lateview.aspx主要是使用了一个DataList控件来显示数据,使用DataList控件来显示数据时,在页面设计时会出现如上所示的重复显示的情况,这是正常的情况,因此见到这种情况不要认为是自己哪里弄错了,其实是没有错的。使用DataList控件显示数据时,需要回到源码视图中手动绑定数据源,部分截图如下图所示:在ItemTemplate模版中插入一个表格,然后在表格的单元格中插入一个Label控件用来显示信息,Label控件的Text属性都写成了“Text="<%#Eval("dept_name")%>"”这种形式,这就是绑定相关的查询字段,显示相关查询字段的信息。lateview.aspx.cs相关代码如下:usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Data.SqlClient;publicpartialclasslateview:System.Web.UI.Page{DBdb=newDB();//创建数据库使用对象protectedvoidPage_Load(objectsender,EventArgse){if(Session["username"]!=null){//这个功能的实现难点在于SQL语句的编写,SQL语句包含了大量的选择逻辑。intlateId=int.Parse(Request["lateId"].ToString());stringsql="selectdepartment.dept_name,special.spc_name,class.class_name,region.region_name,stuInfo.stu_name,stuInfo.room,late.late_time,late.late_introfromdepartment,special,class,stuInfo,region,latewherestuInfo.dept_id=department.dept_idandstuInfo.spc_id=special.spc_idandstuInfo.class_id=class.class_idandlate.stu_id=stuInfo.stu_idandlate.region_id=region.region_idandlate.late_id="+lateId;//Response.Write(sql);//调试SQL语句是否正常//Response.End();DataTabledt=db.reDt(sql);DataList1.DataSource=dt;DataList1.DataBind();}else{Response.Write("");Response.Write("");}}protectedvoidbtnBack_Click(objectsender,EventArgse){Response.Redirect("latecheck.aspx");}protectedvoidbtnDelete_Click(objectsender,EventArgse){intpower=int.Parse(Session["Power"].ToString());//取出保存在Session对象中的用户使用权限标识if(power!=1)//如果登录者不是管理员{Response.Write("");
btnDelete.Enabled=false;//让删除按钮失效}else{//只有管理员才有删除的权限intlateId=int.Parse(Request["lateId"].ToString());stringsql="deletefromlatewherelate_id="+lateId;try{intflag=db.sqlEx(sql);if(flag>0){Response.Write("");Response.Write("");}else{Response.Write("");}}catch(System.Exceptionee){Response.Write("");}}}}lateview.aspx.cs的后台代码编写中,在页面加载时,就获取用户在latecheck.aspx页面中点击【查看】超链接时传递过来的参数lateId,此参数用于标识当前要查看晚归记录的是哪一条,继而显示与该晚归编号相对应的学生的相关信息。该参数的设置在latecheck.aspx页面中使用GridView控件绑定数据源时就已经定义好了,如下图所示:
这里的显示详细信息的难点也是难在SQL语句的编写,这条多表联合查询语句stringsql="selectdepartment.dept_name,special.spc_name,class.class_name,region.region_name,stuInfo.stu_name,stuInfo.room,late.late_time,late.late_introfromdepartment,special,class,stuInfo,region,latewherestuInfo.dept_id=department.dept_idandstuInfo.spc_id=special.spc_idandstuInfo.class_id=class.class_idandlate.stu_id=stuInfo.stu_idandlate.region_id=region.region_idandlate.late_id="+lateId;涉及到的表有department,special,class,stuInfo,region,late六个表以及复杂的查询条件,组合查询条件的关键点也是根据各个表之间建立的主键外键的约束关系找到各个表的联系条件。这里除了显示某个有晚归记录的学生的详细信息外,还有一个删除功能,只有管理员才具有删除权限,因此在进行删除功能的编写时,首先要把保存在Session对象的用户使用权限取出来进行判断,如果取出来的权限不是管理员所具有权限,那么就表示登录者的身份是学生或者是记录员,此时就不能让这两种身份的人删除记录,因此当这两种身份的人点击【删除】按钮时,就让弹出提示信息,并让【删除】按钮失效,这样就可以防止除管理员之外的其他身份的人删除了。如果是管理员身份登录,那么当管理员点击【删除】按钮时,就直接删除记录。【返回】按钮要实现的功能是点击【返回】按钮时返回到查询页面即可。比较简单。这里不再陈述。到此,显示详细信息的功能全部实现。实现晚归汇总功能模块latecount.aspx页面的设计如下所示:这里也是使用GridView控件显示数据,数据源也是采用手动绑定的方式绑定到GridView控件中。这里要实现的功能也和晚归查询的功能是一致的,都是要根据用户选择的查询条件查询出用户想要的汇总情况。
查询逻辑和晚归查询的逻辑是一致的,唯一不同的是多表联合查询的表不一样。相关代码如下所示:protectedvoidbtnSearch_Click(objectsender,EventArgse){/*这两种SQL语句的写法都可以,哪一种比较容易理解就使用哪一种*///stringsql="selectstuInfo.stu_nameAS姓名,COUNT(late.stu_id)AS晚归次数,class.class_nameAS班级FROMlateINNERJOINstuInfoONlate.stu_id=stuInfo.stu_idINNERJOINclassONstuInfo.class_id=class.class_idGROUPBYlate.stu_id,stuInfo.stu_name,class.class_name";//stringsql="selectstuInfo.stu_name姓名,count(late.stu_id)as晚归次数,班级=class.class_namefromstuInfo,late,classwherestuInfo.stu_id=late.stu_idandstuInfo.class_id=class.class_idgroupbylate.stu_id,stuInfo.stu_name,class.class_name";//这里的写法包含了别名的三种表示方法stringdept_Id=dp_selectDept.SelectedValue;stringspc_Id=dp_selectSpec.SelectedValue;stringclass_Id=dp_selectClass.SelectedValue;stringregion_Id=dp_selectRegion.SelectedValue;stringstartime=txtStartTime.Text;stringendtime=txtEndTime.Text;stringroom=txtRoom.Text;stringname=txtName.Text;stringsql="selectstuInfo.stu_name姓名,count(late.stu_id)as晚归次数,班级=class.class_namefromstuInfo,late,classwherestuInfo.stu_id=late.stu_idandstuInfo.class_id=class.class_id";stringsqlend="groupbylate.stu_id,stuInfo.stu_name,class.class_name";//注意:这里的group前面有一个空格,这个空格千万不能少,否则SQL语句的组合会出错if(dept_Id==""&&spc_Id==""&&class_Id==""&®ion_Id==""&&startime==""&&endtime==""&&room==""&&name==""){//如果直接点击查看按钮,就直接显示所有记录sql=sql+sqlend;//将两段SQL语句重新组合}else{//如果用户加上了查询条件if(dept_Id!=""){//如果用户选择了系部,则重新组合SQL语句,加上查询条件——“系部编号”sql+="andstuInfo.dept_id="+dept_Id;}if(spc_Id!=""){sql+="andstuInfo.spc_id="+spc_Id;
}if(class_Id!=""){sql+="andstuInfo.class_id="+class_Id;}if(region_Id!=""){sql+="andlate.region_id="+region_Id;}if(startime!=""&&endtime==""){//sql+="andlate.late_time=""+startime+""";sql+="andlate.late_timelike"%"+startime+"%"";//遗留的问题,如何对时间进行模糊查询}if(endtime!=""&&startime==""){sql+="andlate.late_time=""+endtime+""";}if(startime!=""&&endtime!=""){sql+="andlate.late_timebetween""+startime+""and""+endtime+""";}if(room!=""){//sql+="andstuInfo.room=""+room+""";sql+="andstuInfo.roomlike"%"+room+"%"";//进行模糊查询,使查询更加人性化,用户只需要输入有关宿舍一个关键字就可以找到与关键字相关的记录}if(name!="")
{//sql+="andstuInfo.stu_name=""+name+""";sql+="andstuInfo.stu_namelike"%"+name+"%"";//进行模糊查询,使查询更加人性化,用户只需要输入姓名中的一个关键字就可以找到与关键字相关的记录}sql=sql+sqlend;//在这里将汇总时需要进行分组的sqlend语句重新组合到SQL语句中}//Response.Write(sql);//调试SQL语句//Response.End();DataTabledt=db.reDt(sql);GridView1.DataSource=dt;//将数据源绑定到GridView控件GridView1.DataBind();//单击查询按钮时就显示用户需要的数据数据}这里的汇总功能的实现的难点在于如何书写汇总数据的SQL语句,这里的汇总SQL语句使用了汇总函数count(),汇总的字段为学生学号(stu_id),使用多表联合查询并且需要使用汇总函数count()时一定要和groupby(分组)一起使用,并且查询的字段要出现在分组字段中,否则会出错。到此,晚归汇总功能模块就实现了。到此,晚归情况管理功能模块的三个子模块就全部实现了。考勤情况管理功能模块和晚归情况管理功能模块要实现的功能几乎是一模一样的,只要能做出晚归情况管理功能模块就一定能做出考勤情况管理功能模块,因此当要实现考勤情况管理功能模块时,直接在晚归情况管理功能模块上稍作修改即可。为此,关于考勤情况管理功能模块的具体实现过程不再陈述,下面是关于此功能模块的页面设计和关键代码attendcheck.aspx页面的设计如下:
实现查询功能的关键代码如下:protectedvoidbtnSearch_Click(objectsender,EventArgse){stringsql="selectstuInfo.stu_name,class.class_name,attendtype.type_name,attendance.counts,attendance.attend_intro,attendance.attend_time,attendance.attend_idfromstuInfo,class,attendance,attendtypewherestuInfo.class_id=class.class_idandstuInfo.stu_id=attendance.stu_idandattendtype.type_id=attendance.type_id";/*如果用户没有选择查询条件,只是单击查询按钮,就只执行这条SQL语句,将全部的记录查询出来*/stringdept_Id=dp_selectDept.SelectedValue;stringspc_Id=dp_selectSpec.SelectedValue;stringclass_Id=dp_selectClass.SelectedValue;stringtype_id=dp_event.SelectedValue;stringstartime=txtStartTime.Text;stringendtime=txtEndTime.Text;stringroom=txtRoom.Text;stringname=txtName.Text;if(dept_Id!=""){//如果用户选择了系部,则重新组合SQL语句,加上查询条件——“系部编号”sql+="andstuInfo.dept_id="+dept_Id;}if(spc_Id!=""){sql+="andstuInfo.spc_id="+spc_Id;}if(class_Id!=""){sql+="andstuInfo.class_id="+class_Id;}if(type_id!=""){sql+="andattendance.type_id="+type_id;}if(startime!=""&&endtime==""){//sql+="andlate.late_time=""+startime+""";sql+="andlate.late_timelike"%"+startime+"%"";//遗留的问题,如何对时间进行模糊查询}if(endtime!=""&&startime=="")
{sql+="andlate.late_time=""+endtime+""";}if(startime!=""&&endtime!=""){sql+="andlate.late_timebetween""+startime+""and""+endtime+""";}if(room!=""){//sql+="andstuInfo.room=""+room+""";sql+="andstuInfo.roomlike"%"+room+"%"";//进行模糊查询,使查询更加人性化,用户只需要输入有关宿舍一个关键字就可以找到与关键字相关的记录}if(name!=""){//sql+="andstuInfo.stu_name=""+name+""";sql+="andstuInfo.stu_namelike"%"+name+"%"";//进行模糊查询,使查询更加人性化,用户只需要输入姓名中的一个关键字就可以找到与关键字相关的记录}//Response.Write(sql);//调试语句,用于调试SQL语句是否正常//Response.End();//程序执行到这里以后就不再往下执行了DataTabledt=db.reDt(sql);GridView_DataShow.DataSource=dt;//绑定数据源到GridView_DataShowGridView_DataShow.DataBind();//显示数据}attendcount.aspx的页面设计如下:
实现查询汇总功能的关键代码如下protectedvoidbtnSearch_Click(objectsender,EventArgse){/*这两种SQL语句的写法都可以,哪一种比较容易理解就使用哪一种*///stringsql="selectstuInfo.stu_nameAS姓名,COUNT(late.stu_id)AS晚归次数,class.class_nameAS班级FROMlateINNERJOINstuInfoONlate.stu_id=stuInfo.stu_idINNERJOINclassONstuInfo.class_id=class.class_idGROUPBYlate.stu_id,stuInfo.stu_name,class.class_name";//stringsql="selectstuInfo.stu_name姓名,count(late.stu_id)as晚归次数,班级=class.class_namefromstuInfo,late,classwherestuInfo.stu_id=late.stu_idandstuInfo.class_id=class.class_idgroupbylate.stu_id,stuInfo.stu_name,class.class_name";//这里的写法包含了别名的三种表示方法stringdept_Id=dp_selectDept.SelectedValue;stringspc_Id=dp_selectSpec.SelectedValue;stringclass_Id=dp_selectClass.SelectedValue;stringtype_id=dp_event.SelectedValue;stringstartime=txtStartTime.Text;stringendtime=txtEndTime.Text;stringroom=txtRoom.Text;stringname=txtName.Text;stringsql="selectstuInfo.stu_name姓名,count(attendance.stu_id)as考勤次数,班级=class.class_namefromstuInfo,attendance,classwherestuInfo.stu_id=attendance.stu_idandstuInfo.class_id=class.class_id";stringsqlend="groupbyattendance.stu_id,stuInfo.stu_name,class.class_name";//注意:这里的group前面有一个空格,这个空格千万不能少,否则SQL语句的组合会出错if(dept_Id==""&&spc_Id==""&&class_Id==""&&type_id==""&&startime==""&&endtime==""&&room==""&&name==""){//如果直接点击查看按钮,就直接显示所有记录sql=sql+sqlend;//将两段SQL语句重新组合}else{//如果用户加上了查询条件if(dept_Id!=""){//如果用户选择了系部,则重新组合SQL语句,加上查询条件——“系部编号”sql+="andstuInfo.dept_id="+dept_Id;}if(spc_Id!=""){sql+="andstuInfo.spc_id="+spc_Id;
}if(class_Id!=""){sql+="andstuInfo.class_id="+class_Id;}if(type_id!=""){sql+="andattendance.type_id="+type_id;}if(startime!=""&&endtime==""){//sql+="andlate.late_time=""+startime+""";sql+="andlate.late_timelike"%"+startime+"%"";//遗留的问题,如何对时间进行模糊查询}if(endtime!=""&&startime==""){sql+="andlate.late_time=""+endtime+""";}if(startime!=""&&endtime!=""){sql+="andlate.late_timebetween""+startime+""and""+endtime+""";}if(room!=""){//sql+="andstuInfo.room=""+room+""";sql+="andstuInfo.roomlike"%"+room+"%"";//进行模糊查询,使查询更加人性化,用户只需要输入有关宿舍一个关键字就可以找到与关键字相关的记录}if(name!="")
{//sql+="andstuInfo.stu_name=""+name+""";sql+="andstuInfo.stu_namelike"%"+name+"%"";//进行模糊查询,使查询更加人性化,用户只需要输入姓名中的一个关键字就可以找到与关键字相关的记录}sql=sql+sqlend;//在这里将汇总时需要进行分组的sqlend语句重新组合到SQL语句中}//Response.Write(sql);//调试SQL语句//Response.End();DataTabledt=db.reDt(sql);GridView1.DataSource=dt;//将数据源绑定到GridView控件GridView1.DataBind();//单击查询按钮时就显示用户需要的数据数据}attendwrite.aspx页面的设计如下:实现考勤记录的关键代码如下:protectedvoidbtnRecord_Click(objectsender,EventArgse){stringstuId=dp_name.SelectedValue;//从选中的dp_name的项的value获取到stu_idstringtype_id=dp_event.SelectedValue;//从选中的dp_event的项的value获取到type_idstringcounts=dp_course.SelectedValue;//获取选中的课时if(stuId!=""&&counts!=""&&counts!=""){DateTimeattend_time=DateTime.Parse(txtTime.Text.Trim());//获取从文本框输入的晚归时间字符串,并把字符串转换成真正的时间类型stringattend_intro=txtContent.Text.Trim();//获取输入的晚归事由,Trim()方法的作用是截断字符串左右两边的空格stringsql="insertintoattendance(stu_id,type_id,attend_time,attend_intro,counts)values(""+stuId+"","+type_id+",""+attend_time+"",""+attend_intro+"","+counts+")";//Response.Write(sql);//Response.End();try
{intflag=db.sqlEx(sql);if(flag>0){Response.Write("");txtContent.Text="";txtTime.Text="";}else{Response.Write("");}}catch(System.Exceptionee){Response.Write("");}}else{Response.Write("");}}attendview.aspx页面的设计如下该页面的设计和lateview.aspx的页面设计是一样的,都是使用DataList控件显示数据,并且也需要回到源码视图手动绑定数据源,如下图
实现详细显示数据的关键代码如下:usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Data.SqlClient;publicpartialclasslateview:System.Web.UI.Page{DBdb=newDB();//创建数据库使用对象protectedvoidPage_Load(objectsender,EventArgse){if(Session["username"]!=null){//这个功能的实现难点在于SQL语句的编写,SQL语句包含了大量的选择逻辑。intattendId=int.Parse(Request["attendId"].ToString());stringsql="selectdepartment.dept_name,special.spc_name,class.class_name,attendtype.type_name,stuInfo.stu_name,attendance.counts,attendance.attend_time,attendance.attend_introfromdepartment,special,class,stuInfo,attendtype,attendancewhere
stuInfo.dept_id=department.dept_idandstuInfo.spc_id=special.spc_idandstuInfo.class_id=class.class_idandattendance.stu_id=stuInfo.stu_idandattendance.type_id=attendtype.type_idandattendance.attend_id="+attendId;//Response.Write(sql);//调试SQL语句是否正常//Response.End();DataTabledt=db.reDt(sql);DataList1.DataSource=dt;DataList1.DataBind();}else{Response.Write("");Response.Write("");}}protectedvoidbtnBack_Click(objectsender,EventArgse){Response.Redirect("attendcheck.aspx");}protectedvoidbtnDelete_Click(objectsender,EventArgse){intpower=int.Parse(Session["Power"].ToString());//取出保存在Session对象中的用户使用权限标识if(power!=1)//如果登录者不是管理员{Response.Write("");btnDelete.Enabled=false;//让删除按钮失效}else{//只有管理员才有删除的权限intlateId=int.Parse(Request["lateId"].ToString());stringsql="deletefromlatewherelate_id="+lateId;try{intflag=db.sqlEx(sql);if(flag>0){Response.Write("");Response.Write("");}else{
Response.Write("");}}catch(System.Exceptionee){Response.Write("");}}}}这里编写的代码和lateview.aspx.cs编写的代码几乎一模一样,所以可以直接从lateview.aspx.cs中将代码复制过来,再修改一下要查询的表和字段即可。到此,考勤情况管理模块的三个子模块的功能全部实现了。由于晚归情况管理模块和考勤情况管理模块这两个模块有很多相似的地方,所有实现考勤情况管理模块时大部分的代码都无需再次编写,只需要从晚归情况管理模块进行相关的复制粘贴再稍作修改即可实现考勤情况管理模块的全部功能。到此,整个系统的最核心的两个功能模块也就全部实现了。整个系统的开发难点就是这两个模块的开发,开发中难就难在如何写出包含了复杂的查询逻辑的SQL语句,相信只要真的弄懂了主键外键约束对各个表的关联的影响,要写出SQL语句也是不难的。我做这个系统写出了很多非常复杂的SQL语句,并且真正明白了主键约束和外键约束的巨大作用。设置主键约束和外键约束最大的作用是可以让各个表之间通过某些关联的字段连接起来,形成一种互相依赖的关系,既有利于保持数据的完整性,也加强了各个表之间的联系。后台管理模块涉及到的都是一些基本的增加、修改、删除功能,主要是涉及到对系部、区门、专业、班级的修改,这些功能上的实现逻辑都是一样的,在此,以区/门维护为例,实现对区/门的更新操作如下:updateRegion.aspx的页面设计如下:实现添加功能时,首先要判断,要增加的区/门是否已经存在,如果已经存在,就弹出提示信息,告诉此用户。如果不存在,就把新的区/门添加到region表中。实现修改功能时,首先要从下拉框中选择好要修改的区/门,然后在文本框中输入修改后的区/门名称,然后将修改后的区/门名称写入到数据库即可。实现删除功能时,从文本框输入要删除的区/门名称,在后台处理中首先会判断数据库中是否存在有和用户输入的区/门名称对应的记录,如果有,就允许执行删除操作,如果没有对应的记录,就弹出提示信息,表明要删除的区/门不存在。实现代码如下:usingSystem;usingSystem.Data;
usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Data.SqlClient;publicpartialclassupdateregion:System.Web.UI.Page{DBdb=newDB();protectedvoidPage_Load(objectsender,EventArgse){if(!IsPostBack){stringsql="";sql="selectregion_id,region_namefromregion";SqlDataReaderdr=db.reDr(sql);dp_selectRegion.DataSource=dr;dp_selectRegion.DataValueField="region_id";dp_selectRegion.DataTextField="region_name";dp_selectRegion.DataBind();//显示数据dp_selectRegion.Items.Insert(0,newListItem("==请选择区/门==",""));}}protectedvoidregion_btnAdd_Click(objectsender,EventArgse){stringregionName=txtRegionName.Text.Trim();stringsq="select*fromregionwhereregion_name=""+regionName+""";stringsql="insertregion(region_name)values(""+regionName+"")";SqlDataReaderdr=db.reDr(sq);if(dr.Read()){Response.Write("");Response.Write("");}else{try{intflag=db.sqlEx(sql);if(flag>0){
Response.Write("");}else{Response.Write("");}}catch(System.Exceptionee){Response.Write("");}}}protectedvoidregion_btnUpdate_Click(objectsender,EventArgse){stringregionName=txtRegionName.Text.Trim();stringregionId=dp_selectRegion.SelectedValue;stringsql="updateregionsetregion_name=""+regionName+""whereregion_id="+regionId;if(regionId!=""){try{intflag=db.sqlEx(sql);if(flag>0){Response.Write("");txtRegionName.Text="";}else{Response.Write("");}}catch(System.Exceptionee){Response.Write("");}}else{Response.Write("");}}protectedvoidregion_btnDelete_Click(objectsender,EventArgse){
stringregionName=txtRegionName.Text.Trim();stringsq="select*fromregionwhereregion_name=""+regionName+""";stringsql="deletefromregionwhereregion_name=""+regionName+""";SqlDataReaderdr=db.reDr(sq);if(dr.Read()){try{Response.Write(sql);Response.End();intflag=db.sqlEx(sql);if(flag>0){Response.Write("");txtRegionName.Text="";}else{Response.Write("");}}catch(System.Exceptionee){Response.Write("");}}else{Response.Write("");}}}到此,区/门维护的全部功能都已经实现系/专业/班级维护功能的实现与区/门维护功能的实现大同小异,这里不再陈述,updatedept.aspx页面设计如下图所示:
详细代码请参考updatedept.aspx.cs文件用户管理模块功能的实现updateadmin.aspx的页面设计如下:用户管理功能模块要实现的只是修改用户的密码功能,从下拉框中选择要修改的帐户,然后输入新的密码,然后再输入管理员密码确认当前执行修改操作的人是否是管理员,只有管理员才会有修改用户信息的权限。功能实现起来比较简单,这里不再陈述。注销用户功能注销功能的作用是注销当前用户,退出系统,回到系统登录页面,实现起来比较简单,当用户点击【注销】超链接时,跳转到注销页面exit.aspx,注销页面不需要进行任何的页面设计,只需要在后台中编写注销功能并实现页面跳转的代码即可,相关代码如下:usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;publicpartialclassexit:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){Session.Abandon();//注销用户Response.Write("");Response.Write("");}}到此,整个系统的全部功能都已经全部实现,整个系统的开发也就结束了。总结:这次的晚归考勤管理信息系统采用ASP.NET技术进行开发,在这次系统开发中,真正地把本学期学习的SQLServer数据库知识与ASP.NET的知识串联起来了,数据库知识里面用到了创建数据库,数据表,设置主键、外键约束,以及学习任何数据库都必须要熟练掌握的SQL语句,在这个系统开发中,核心功能实现的关键的地方都是复杂的SQL语句的书写,有些核心功能难就难在了一条SQL语句的书写,SQL语句书写中难就难在包含了大量查询逻辑的查询语句的书写,查询功能也是整个系统中最核心的功能部分,也是最难实现的部分,是否写得出混杂了大量查询逻辑的查询语句决定了能否实现核心查询功能。ASP.NET技术中用到的知识有:基本的C#语法知识,常用的服务器控件,ASP.NET的一些常用内置对象Response,Request,Session以及操作数据库必须使用的ADO.NET组件,所有有关访问数据库的操作都必须使用ADO.NET组件去执行操作。在这次系统开发中,我写出了以前从来没有写过的涉及到多个表的联合查询语句,我的SQL语句的书写能力得到了进一步的提升,并且学习到了一些设计数据库的技巧,如何让数据库中冗余的数据尽可能地没有,各个表之间如何建立关联。在编写查询语句时,如何动态加上查询条件,再动态拼凑查询语句,这些都是一些以前从来没有使用过的技巧。通过这次系统开发,我的编程能力也得到了进一步的提升,积累了一些项目开发经验,以及项目开发中的一些技巧和功能的实现。虽然这个系统的功能我大部分已经实现,但是还是有些小细节的地方处理不好,这些都有待改进,限于所学的知识有限,目前实在是不懂如何去处理这些小细节。而且我发现这次系统的开发中,存在了很多重复的代码,但一时间我也想不出如何去优化的做法。这次的晚归考勤信息管理系统是我使用ASP.NET+SQLServer2005技术做出来的第一个项目,我不仅学到了很多,而且也很有成就感。编程的乐趣:没有你做不到的,只有你想不到的。