本系统是C/S(客户端/服务器)两层结构。采用C#数据库编程语言。服务器部分是SQL Server2000 关系数据库。客户端分为学生选课子系统和管理员管理子系统,它们通过存于后台数据库的数据产生联系。
无论是学生子系统还是管理员子系统,都需要从数据库中读取院系的信息以及每个院系所开设的课程信息,将其存放在DataSet里面,然后把数据绑定到控件并显示出来。由于每个院系都开设多门课程供学生选择,院系信息和课程信息形成一个树状的结构,所以使用TreeViewer控件显示这些信息比较合适。
通过询问参与选课的学生及负责选课工作的老师具体总结出网上选课系统需要能够实现以下功能:
整个系统的流程是在用户的要求下进行的,学生子系统负责处理学生的选课,退选,增选等事务,并向用户显示操作情况对话框,同时更新数据库中相关表的数据。管理员子系统负责处理管理员对选课情况的管理,向管理员显示操作情况对话框,同时更新数据库中相关表的数据。
系统的数据流图如下:
管理员子系统
简化的数据字典
(1)口令: 用户身份验证
(2)数据流:事务 = [ 输入 | 查询 |选课|]
事务 = [ 输入 | 查询 |退选|]
事务 = [ 输入 | 查询 |增选|]
事务 = [ 输入 | 查询 |修改|]
(3)数据库 = Courses表 + Student表 + Department表 + Elective表 + Admins表 + Period表
后台数据库据库采用SQL Server 2000,各表完成如下功能:
通过对用户提出要求的调查研究,明确了系统设计的目标,确定了系统的基本功能,并分析出数据的流动方向,在此基础之上可以开始着手设计系统,勾画出网上选课系统总体框架。
设计原理
本系统是C/S(客户端/服务器)两层结构.
服务器采用SQL Server2000关系数据库.数据库里存放着编译好的存储过程,主要负责数据的存取,也负责一些的业务逻辑的处理,例如判断学生是否在允许时间段内选课.
客户端包含两个系统:学生选课子系统和管理员管理子系统.学生子系统安装在学校公共机房,图书馆等场所的电脑上,供学生选课时使用,通过局域网访问教务处办公室的服务器;管理员子系统安装在教务处办公室的桌面型电脑上,供管理教务的教师使用.
客户端的设计
学生选课子系统结构图:
各模块完成以下功能:
查看课程信息:学生登录后,查看可供选择的课程信息。
查看已选课程信息:学生登录后,查看自己选择了哪些课程。
选修课程:学生登录后,通过此模块完成选课操作。
退选课程:学生登录后,通过此模块完成退选操作。
管理员子系统结构图:
各模块完成以下功能:
管理学生记录:管理员登录后,可以删除,修改,增加学生信息。
管理课程记录:管理员登录后,可以删除,修改,增加可选课程信息。
修改课程期限:管理员登录后,可以修改选修课程的开始及结束日期。
查看选课情况:管理员登录后,可以查看某门选修课已选人数是否达到限选人数,并可以查看总体选课情况。
数据库的设计
本系统后台数据库建立6个表:Courses表,Students表Departments表,Elective表,Admins表,和Period表。
Name |
Data Type |
Size |
CourseID |
int |
4 |
CourseName |
varchar |
50 |
DepartmentID |
int |
4 |
CourseHours |
int |
4 |
CourseScore |
int |
4 |
CourseTeacher |
varchar |
50 |
UpperLimitStudentNumber |
int |
4 |
SelectedStudentNumber |
int |
4 |
2.Student表
Name |
Data Type |
Size |
StudentID |
int |
4 |
StudentNumber |
varchar |
50 |
Name |
nvarchar |
50 |
Password |
varchar |
50 |
3.Departments表
Name |
Data Type |
Size |
DepartmentID |
int |
4 |
DepartmentNume |
varchar |
50 |
4.Elective表
Name |
Data Type |
Size |
ElectiveID |
int |
4 |
StudentID |
int |
4 |
CourseID |
int |
4 |
5.Admins表
Name |
Data Type |
Size |
AdminID |
int |
4 |
UserName |
varchar |
50 |
Name |
nvarchar |
50 |
Password |
varchar |
50 |
6.Period表
Name |
Data Type |
Size |
PeriodID |
int |
4 |
BeginTime |
datetime |
8 |
EndTime |
datetime |
8 |
Note |
varchar |
50 |
到了确定应该怎样具体的实现所要求的系统的时候了,这个阶段将得出学生选课系统的精确描述,从而在编码阶段可以把这个描述直接翻译成具体的程序设计语言书写的程序,这一阶段的结果直接决定了最终程序代码的质量。
1.人机界面设计
本系统对每一层都设置了确保安全的障碍和入口,用户只有进入了某一层才能获得相应那一层资源的访问权,这些措施保证了选课系统及具体数据的安全性。任何一位Web用户在进入选课系统主页面后,只有通过了系统的身份验证才能进入到系统相应的功能页面完成所要进行的操作。
本系统主要包含以下界面:
从此界面,可以分别进入管理员子系统、学生子系统登录界面,单击查询可以查看课程信息并可以查看打印预览。
在该界面学生输入学号、密码,单击登录按钮系统进行验证身份,如学号、密码与数据库中的记录吻合,则进入下一个界面,进行选课。
管理员登录后,可以添加课程、查看选课情况、对学生记录进行管理等,本界面为学生管理界面,管理员输入学生学号,单击查找按钮,在姓名和密码栏中显示该学生的信息,单击修改按钮或删除按钮,就可以完成相应操作。
在添加学生记录一栏中填写相应信息,单击添加按钮,该学生信息就可以添加到数据库中。
用户可以从主页直接进入成绩查询界面,用户可以通过此界面查看课程信息,分别可以按系、按课程名称、按授课教师等查询课程信息,这样大大方便了各级用户,使用户可以更直接、更方便的了解各门课程,有利于学生快速、准确的选课,同时也有利于管理员对课程的管理。通过打印预览子菜单,用户可以将所需信息打印出来。
本报表的制作采用Crystal Report Designer,Crystal Reports for Visual Studio.NET是内置于Visual Studio.NET的报表设计工具,它能够在.NET平台上创建高复杂度且专业级的互动式报表,其以Crystal Report8.0的架构为基础,并且针对.NET平台作更进一步的强化与发展,以确保能提供.NET开发人员最丰富且完整的报表功能。
本系统利用此报表反馈出各系开设课程信息,既方便了学生选课,又减轻了管理员的管理负担,并同时提供打印功能,方便了管理员对局域网上各系开设课程总体情况的掌握。
制作报表过程如下:
首先在原有项目下创建新的窗体,从“工具箱”的Windows窗体选项卡中将CrystalReportViewer报表查看器控件拖放至窗体上,然后从“项目”菜单中选取“添加新项”指令,选择添加Crystal Report项,接下来选择作为空白报表一项,单击确定,即可编辑具有自己独特风格的报表了。需要说明的是:报表的数据源可由窗口左侧的数据库文件直接设定。
此界面为配置管理界面,管理员通过相关操作,可以直接修改数据库中的选课时间记录。在文本区键入选课开始、结束时间,单击生成按钮,配置文件生成功,为更新数据库作好第一步准备。
单击读取按钮,将配置文件读入内存,以便通过函数调用UpdatePeriod存储过程,更新数据库。出现更新数据库成功对话框,单击确定按钮,此时数据库记录被修改。学生必须按照新的选课时间进行选课,使管理员可以动态的、间接的管理数据库,而无须登录到SQL Server2000企业管理器对数据库进行修改。
本网上选课系统共涉及到12个用户界面,以上是具有代表性的几个,单独列出加以说明。为了提高代码的重用性和封装对存储过程的调用,每个子系统都实现了一个存取数据的公共类,提供本系统使用。
2.过程设计
本系统对每一层都设置了确保安全的障碍和入口,用户只有进入了某一层才能获得相应那一层资源的访问权,这些措施保证了选课系统及具体数据的安全性。
不同身份的用户拥有对数据库的不同访问权限(具体到对库中每个表的存取操作),学生用户的选/退课权限通过系统应用程序提供给教务管理人员动态设置。
系统程序流程图如下
3.3编码
源程序代码的逻辑应简明清晰,易读易懂,编码必须严格遵循详细设计阶段的结果,编写出严密、有逻辑性的代码。
本应用程序为了提高服务器数据库的访问效率,加快整个系统的运行速度,存取数据全部使用存储过程。同时对一些业务逻辑也使用了一些存储过程。
分别使用如下代码进行数据库连接:
private string m_strConnString;
private SqlConnection m_connConnection;
打开操作:
public void Open(string strDataSource,string strInitialCatalog,string strUserID,string strPwd)
{
m_strConnString="Data Source="+strDataSource+";Initial Catalog="+strInitialCatalog+";User ID="+"sa"+";Password="+strPwd;
m_connConnection= new SqlConnection(m_strConnString);
m_connConnection.Open();
}
关闭操作:
public void Close()
{
m_connConnection.Close();
}
首先创建CSQL类,当类中某一对象需要获取数据库中的数据时,用如下代码调用Open()函数。
CSQL mySQL=new CSQL();
mySQL.Open("localhost","electcourses","sa","2188");
其中localhost表示本地访问,electcourses为数据库名,sa为数据库用户名,2188为用户口令。
MySQL.Close();
使用该语句可以直接关闭数据库。
各模块具体实现代码如下:
学生子系统:
private void FillDirectoryTree()
{
CSQL mySQL =new CSQL();
mySQL.Open("localhost","electcourses","sa","2188");
DataSet DepartmentDS = mySQL.GetDataSet("select * from Departments","departments");
int myCount = DepartmentDS.Tables["departments"].Rows.Count;
mySQL.Close();
for(int i=0;i
{
string DepartmentName = DepartmentDS.Tables["departments"].Rows[i][1].ToString();
int DepartmentID = int.Parse(DepartmentDS.Tables["departments"].Rows[i][0].ToString());
TreeNode CRoot = new TreeNode(DepartmentName);
treeView1.Nodes.Add(CRoot);
AddDirectories(CRoot,DepartmentID);
}
}
private void AddDirectories(TreeNode node,int departmentid)
{
CSQL mySQL =new CSQL();
mySQL.Open("localhost","electcourses","sa","2188");
DataSet ds = new DataSet();
string strsqltemp = "select * from Courses where DepartmentID="+departmentid.ToString();
ds = mySQL.GetDataSet(strsqltemp,"courses");
int myCount = ds.Tables["courses"].Rows.Count;
for(int i=0;i
{
string CourseName = ds.Tables["courses"].Rows[i][1].ToString();
node.Nodes.Add(new TreeNode(CourseName));
}
mySQL.Close();
}
CREATE Procedure ElectiveList
(
@StudentID int
)
AS
SELECT
Courses.CourseID,
Courses.CourseName,
Courses.CourseTeacher,
Courses.CourseScore,
Courses.CourseHours
FROM
Elective
INNER JOIN Courses ON Courses.CourseID=Elective.CourseID
WHERE
Elective.StudentID=@StudentID
GO
CREATE Procedure ElectCourse
(
@StudentID int,
@CourseID int,
@ElectiveID int OUTPUT
)
AS
INSERT INTO Elective
(
StudentID,
CourseID
)
VALUES
(
@StudentID,
@CourseID
)
SELECT
@ElectiveID=@@Identity
GO
CREATE Procedure CancelCourse
(
@StudentID int,
@CourseID int,
@ElectiveID int OUTPUT
)
AS
SELECT
@ElectiveID=ElectiveID
FROM
Elective
WHERE
@StudentID=StudentID
AND
@CourseID=CourseID
DELETE FROM
Elective
WHERE
(
@StudentID=StudentID
AND
@CourseID=CourseID
)
GO
管理员子系统
CREATE Procedure ModifyStudentInfo
(
@StudentNumber nvarchar(50),
@Name nvarchar(50),
@Password nvarchar(50)
)
AS
UPDATE Students
SET
Name=@Name,
Password=@Password
WHERE
StudentNumber=@StudentNumber
GO
CREATE Procedure AddStudent
(
@StudentNumber nvarchar(50),
@Name nvarchar(50),
@Password nvarchar(50),
@StudentID int OUTPUT
)
AS
INSERT INTO Students
(
StudentNumber,
Name,
Password
)
VALUES
(
@StudentNumber,
@Name,
@Password
)
SELECT
@StudentID=@@Identity
GO
CREATE Procedure DeleteStudent
(
@StudentNumber nvarchar(50),
@Name nvarchar(50)
)
AS
DELETE Students
WHERE
StudentNumber=@StudentNumber
AND
Name=@Name
GO
CREATE Procedure ModifyCourse
(
@CourseID int,
@CourseName nvarchar(50),
@CourseHours int,
@CourseScore int,
@CourseTeacher nvarchar(50),
@UpperLimitStudentNumber int
)
AS
UPDATE Courses
SET
CourseName=@CourseName,
CourseHours=@CourseHours,
CourseScore=@CourseScore,
CourseTeacher=@CourseTeacher,
UpperLimitStudentNumber=@UpperLimitStudentNumber
WHERE
CourseID=@CourseID
GO
CREATE Procedure AddCourse
(
@CourseID int,
@CourseName nvarchar(50),
@DepartmentID int,
@CourseHours int,
@CourseScore int,
@CourseTeacher nvarchar(50),
@UpperLimitStudentNumber int
)
As
INSERT INTO Courses
(
CourseID,
CourseName,
DepartmentID,
CourseHours,
CourseScore,
CourseTeacher,
UpperLimitStudentNumber
)
VALUES
(
@CourseID ,
@CourseName ,
@DepartmentID,
@CourseHours ,
@CourseScore ,
@CourseTeacher,
@UpperLimitStudentNumber
)
SELECT
@CourseID=@@Identity
GO
CREATE Procedure RemoveCourse
(
@CourseID int
)
AS
BEGIN Transaction
DELETE FROM Courses
WHERE
CourseID=@CourseID
DELETE FROM Elective
WHERE
CourseID=@CourseID
if @@rowcount>0
Commit Transaction
else
Rollback Transaction
GO
通过读取XML文件,调用UpdatePeriod存储过程实现更新数据库。
XML文件
<?xml version=”1.0”?>
2005-6-25 12:00
UpdatePeriod存储过程
CREATE Procedure UpdatePeriod
(
@BeginTime datetime,
@EndTime datetime
)
AS
UPDATE Period
SET
BeginTime=@BeginTime,
EndTime=@EndTime
GO
CREATE Procedure ElectiveTotalList
AS
SELECT
Elective.StudentID,
Students.StudentNumber,
Students.Name,
Courses.CourseID,
Courses.CourseName,
Courses.CourseTeacher,
Courses.CourseScore,
Courses.CourseHours
FROM
Elective
INNER JOIN Courses ON Courses.CourseID=Elective.CourseID
INNER JOIN Students ON Students.StudentID=Elective.StudentID
ORDER BY
Elective.StudentID
GO
测试方案:
我采用了白盒测试(又称结构测试),即按照程序内部的逻辑结构,检验程序中的每条通路是否能够按照预定要求正常工作。
由于设计过程当中,不免会出现很多意想不到的结果发生,为了减少不必的错误出现,同时,为了能够使不同的文件之间正确和有效的衔接,我在设计模块的过程,对于每一个文件的执行和模块的执行都做了认真地测试,以求达到设计要求。
测试过程:
主要检查模块的两个方面,一个是各个模块之间的接口,另一个是模块的运行是否正常。
对于检验各个模块之间的接口,所做的测试工作有:
对于检验模块的运行是否正常,所做的测试工作有:
测试结果:
测试结果表明,每一个模块都能够正常独立地运行,各个模块之间的接口亦能正确地吻合,同时每个模块基本上达到了设计的要求。
测试方案
在设计过程中和设计结束不断地进行黑盒测试(又叫功能测试),即检查程序功能是否按照规格说明书的规定正常使用,程序是否能够适当地接收输入数据产生正确的输出信息,并且保持外部信息的完整性。
在这次的设计当中,对于每一个模块的功能实现上和设计风格上,都做了细致的检测,并且尽力去找出系统的纰漏之处。
测试过程
主要由我的导师在不同的时间、不同机器和不同的系统状态下进行测试过程,利用特殊的参数和普通参数两种方式进行测试。
测试结果
测试结果表明,系统能够按照设计的要求实现其内部的各项功能,同时提前
完成了设计的任务要求。
测试方案
我采用黑盒测试,对系统的各个模块功能进行了随机抽样检验,同时作了相应的时间比较。
测试过程
我对所抽样后选择出的模块进行黑盒测试,从以下几个角度进行:
测试结果
测试结果表明,尽最大地可能满足了不同用户的需求,同时保证了系统管理员的高效的管理工作,基本上有效地防止了破坏者的恶意攻击。