@Vany
2016-01-17T06:34:41.000000Z
字数 6400
阅读 2559
唐思远 3110000181
数据库 数据管理系统 设计报告
目录
设计并实现一个图书管理系统,具有图入库、查询、借书、还书、借书证管理等功能。
这里将区分用户权限,对于普通读者(不需要登陆),具有借书和图书查询的权限;对于图书管理员,具有全部权限:图书入库、查询、借书、还书、借书证管理等。特别说明的是,因为还书需要管理员经手还书,所以将还书功能赋予给管理员,而不简单的开放给用户。
这是普通用户的主页:

这是管理员登录后的主页:

数据库中建立了4个表,分别为Book、Record、UserAdmin以及UserReader表,分别表示书目信息、借书/还书信息、管理员信息以及借书证信息。
对于Book书目信息表,具体配置如下:
create table Book(bookID int not null,bookName nvarchar(50) not null,Kind nvarchar(50),Publisher nvarchar(20),Year int,Author nvarchar(30),Price numeric(5,2),num_stored int not null,num_remain int not null,primary key bookID);
其中bookID为主键(primary key)不能为null;bookName一般来说对于一个有意义的记录也不能为空,还有num_stored和num_remain分别表示当前一共有多少本以及库存还剩多少本藏书,这个字段也应为not null。其他的信息可能在添加的同时知道的还不全,因此这里我允许其字段值为null。
对于一般字符串类型,我均考虑到了中文的情况,全部使用nvarchar类型,并根据其特性设置了一定的长度,数字一般为int类型足够用,对于价格这类的属性,我采用了numeric类型,保证精度,限定范围。下面将要叙述的表格也将满足这样的约定。
对于userReader读者(借书证)信息表,其create table语句如下:
create table userReader(cardID int not null,name nvarchar(20),depart nvarchar(20),position nvarchar(10));
每个属性具体含义如字段名所示,这里不再重复了。
对于Record借书/还书信息表,其创建语句如下:
create table Record(cardID int not null,bookID int not null,borrowDate datetime not null,returnDate date not null,returnhandingID int,primary key (cardID,bookID,borrowDate),foreign key cardID userReader(cardID),foreign key bookID Book(bookID));
其中bookID、cardID及borrowDate共同构成联合主键,这是因为这个表中可能存在该借书证之前已经借过而且已经还掉的记录,因此我们必须把borrowDate添加为主键的一个字段以示区别。
最后,是管理员的信息表userAdmin,与userReader表类似,具体语句如下:
create table userAdmin(userName varchar(20) not null,userPwd varchar(20) not null,realName nvarchar(20),phone varchar(20),primary key userName);
这里userName和userPwd即管理员登录时要输入的用户名密码,这里默认都是英文ASCII字符。另外,userName作为主键,以防止重名的管理员存在。
本管理系统采用ASP.NET技术开发,采用C#语言,下面将介绍该系统的架构。整个解决方案的文件目录结构如下图所示:

对于界面方面,这里利用了ASP.NET的模板技术,使用LibSite.Master作为整个网站页面的模板,其中包含效果图中的上端导航栏。该导航栏可以根据用户登录与否自动改变内容。
其余的网页都将通过导航栏的链接进入,不登录状态下只有图书查询、借书功能;管理员登录后还会有还书、图书入库和借书证管理功能。每一个页面都是继承自LibSite.Master模板,即在任何状态下都可以通过导航栏导航之不同的功能。
另外,不同功能类别(模块)的页面文件存在了不同的目录中,例如关于权限管理(Authorization Management)的功能管理员登陆以及借书证管理,被存放在了AuthMgmt目录下;关于图书管理(Book Management)的功能图书入库、图书查找、借书、还书都被放在了BookMgmt目录下;最后Default.aspx在网站的根目录下,作为主页,显示导航栏以及欢迎图片。
整个架构框架如下图所示:

ASP.NET提供了强大的访问数据库的类库。在此程序中,我们主要采用了SqlDataSource类来连接数据库:
SqlDataSource sqlsource = new SqlDataSource() {ConnectionString = ConfigurationManager.ConnectionStrings["dbConnectionString"].ConnectionString};
其中我们可以设置该数据源的SelectCommand、InsertCommand、UpdateCommand以及DeleteCommand,然后执行对应的操作。
对于Insert、Update以及Delete,使用方法类似,这里以Insert为例:
sqlsource.InsertCommand = string.Format("insert into record (cardID, bookID, borrowDate) values({0},{1},'{2}')", txtCardID.Text, txtBookID.Text, DateTime.Now.ToString());int r = sqlsource.Insert(); //r is the status of reuslt, positive is success
调用Insert命令后,会返回一个int表示执行结果,其中正数表示执行成功。
对于Select命令,由于我们需要获取Select后的结果,所以代码会有稍稍不同:
sqlsource.SelectCommand = "select * from book where bookID=" + ID;foreach (DataRowView row in (DataView)sqlsource.Select(DataSourceSelectArguments.Empty))if(row["bookID"].ToString()==xxx)...
在上面的代码过程中我们看到,对于select回来的数据集,我们用foreach来枚举每一行,然后利用row["..."]来获取这一行记录的对应属性的值。
另外,我还采取了ASP.NET自带的GridView控件来显示查询结果。可以静态绑定GridView的DataSource属性为SqlDataSource数据源,也可以动态的赋值,然后执行GridView1.DataBind()函数来动态绑定。
GridView的另一个好处是,只要制定了Delete语句的命令,可以直接添加删除操作的列,该列显示删除连接,可以实现删除功能,具体实例可见借书证管理模块部分。
下面将分模块介绍每个模块的内容,包括模块效果图、实现的功能以及设计的思想与流程图。

图书查询模块实现了图书的按条件查询功能。如果不输入任何条件,那么默认查询所有的数目,并返回对应的信息,如书名、类别、藏书量、库存剩余等等。在查询的结果的表中我们可以点击表头的某个列的名字,实现按照该列的内容排序(默认增序),方便查找与统计。
另外,查询过程中字符串查询(例如书名、类别、作者、出版社这些字段)均采用模糊查询功能,即只要输入要匹配信息的其中一段即可匹配到要找的信息,这里是利用SQL的like%str%并将各个条件利用and连接起来实现的。其他数字相关的查询属性均采用区间查询模式,如年份、价格等,对应到SQL中即between a and b子句。

该模块实现了借书的基本功能,并且可以在借书前查询该借书证所借过的书(未归还的书)。
对于借书操作,首先要判断书库中该书籍是否还有库存,这是必要条件。程序中实现即利用sql语句查询该本书id的记录并判断其库存量是否大于等于零。
如果没有库存,则借书失败,并且显示该书最近归还时间。在实际程序实现中,除了查询最近归还时间需要用到orderby borrowDate子句外,我发现由于记录表(Record)中可能存在该编号的书已还的情况,因此需要在查询最近归还时间时加上归还经手人ID(returnhandingID)为null的条件(即未归还),如下所示
select returnDate from record where bookID={0} and returnhandingID is null orderby borrowDate
另外,还要判断该借书证是否已经借过同样一本书,如果是相同的书籍,且尚未归还,那么不允许重复借书(如果归还了,那么可以再借),查询的具体的sql语句如下
select * from record where cardID={0} and bookID={1} and returnhandingID is NULL
如果上述条件皆满足,那么就可以借书,程序中首先向记录表(Record)中添加一条新借书记录,在添加记录后,sql数据库中触发器被触发(Record表的insert触发器)。在触发器中,会更改Book表中对应书的库存信息。在这个过程中如果没发生错误,那么就借书成功,否则失败。
其中创建触发器的代码如下
create trigger recordInsertTriggeron recordafter insertas beginupdate Book set num_remain=num_remain-1from Book, insertedwhere Book.bookID=inserted.bookIDend

该模块实现了管理员登录的功能,通过判断用户名密码是否在数据库中的管理员信息表中存在,来判断该用户登录信息是否合法。如果登录成功,那么设置Session中的一些变量(例如Session["userName"]及Session["userID"]),用来表示当前登录的管理员信息,并跳转回主页,此时导航栏中会自动多出一些管理员权限的模块(详见前文首页效果图)。
值得说明的是,只有有了此Session信息,用户才可以进入其他只有管理员才有权限操作的功能模块。也就是说,若没有登录(即没有Session信息),强行进入这些功能模块页时会强制跳转回主页(这个功能在那些页面的Form_load事件中实现)。

由于还书必须由管理员经手,因此还书功能是在管理员登陆后才显示出来的功能模块。
点击还书连接,进入还书模块。同样可以先输入借书证号,来查询本借书证已借数目,这在还书时是比较重要的。接着,输入书号,点击还书按钮,即可完成还书功能。
在执行还书的操作中,程序中会先判断该借书证是否借过此书,接着调用update命令,更新记录(Record)表中还书日期以及经手的管理员。与此同时,在执行update后,sql数据库中会调用触发器,来修改该书的库存量,使得数据保持一致性。若在这个过程中发生任何错误,都会还书失败;反之,还书成功。
这里为了节省空间,将图片空白部分裁剪掉了。

对于单本入库功能
对于批量入库功能
该模块同样是管理员权限的模块,需要管理员登录后才可进入。
图书入库功能比较复杂,主要包括两方面内容:单本入库与批量入库。
对于单本入库功能,根据实际情况不同分为两类:新书入库以及已有图书入库。对于图书馆新进的新书(之前没有该编号的图书),我们需要输入较全面的信息,如书名、作者、出版社、书号、入库数量等等,点击新书入库即可实现新书入库功能,数据库中会自然添加一条该数目信息的记录。
如果在上面的操作中,输入了已经存在的书的编号,点击新书入库是不允许的,即在入库前利用select语句判断该书库中是否有同样编号的数目。此时,如果是想入库已经存在的图书,即新增数目,那么我们只要输入书号以及新入库的数量,点击已有图书入库即可实现该功能,程序中利用update命令更新该书目的总库存以及总数量两个属性字段。显然如果我们输入了当前书库中不存在的图书编号,仍点击已有图书入库功能,那么会产生错误,添加失败。
对于批量入库功能,将按照效果图中的说明所说的那样实现功能。细节较繁,具体就不赘述了。

对于显示功能没有什么流程,是页面直接展示出来的。
对于添加借书证过程,流程图如下:
管理员权限下的模块,如果不是管理员权限,则自动跳转回主页。
借书证管理比较简单,主要分为两部分内容,一部分通过GridView控件显示现在的借书证信息,另一部分与新书入库功能类似,填写借书证信息(姓名、单位、卡号以及可选的职位——学生或教师),点击添加按钮即可实现借书证的添加。当然,如果此次添加的借书证卡号已存在,则会添加失败。
如果我们想删除某个借书证,只需要在GridView上点击对应行删除连接即可实现删除操作。