上一节我们简单介绍了数据库的读写,所使用的数据库都是随便写的(用水果代替,但不是真正的食品零售数据表,至少没有价格,销量等等)。这一节我们思考如何实现一个测试题的数据库,所谓的测试题数据库就是假定系统里预存了1000道题目,每个学生考试随机抽查50题,以保证每次考试很难相互抄袭,而且每个题目设置时间限制,到时间不作答就认为放弃,考试完成自动阅卷等等,这些功能都是普通的纸质考试没法实现的。
那么首先就是数据库的设计,能够想到的试题至少包含下面的信息(题目的参考答案和当前答案是一个很难讲的问题,比如选择题有多选的情况,比如简答题没法一一对应的情况,但是为了简化起见还是应该先做成字符串,如果用户回答A,B,C三个而正确答案是AB两个,则错选0分,如果正确答案是ABCD,则漏选得一半分数,这些复杂的逻辑处理要后面慢慢优化,一开始要先把大的框架搭建好)
初步设计成两张表,一个是试题库,一个是考试记录库(可能我们需要统计有多少人参加了考试,考试的结果,每个学生的成绩之类的,表的结构不合理后面可以再修改,基本的功能应该够了)
有了数据库之后,下面一步就是录入试题(对应了数据库的增加),可以想象淘宝网如果没有卖家先把宝贝传到数据库,买家搜不到任何东西,这个网站也没有任何价值,所以数据库首先要有内容,我们要首先设计一个人机界面,给老师录入试题。注意要尽量用最适合的控件,比如编号就是数字上下的控件,试题类型就是combobox,而文本框也要做一些限制,比如只允许输入数字(可以提高软件的用户体验)
把数据库的连接做成一个标准方法,例如我们可以指定在连接的时候需要给目标数据库的路径,密码,数据表的名称(其实还可以做得更复杂,比如不带密码则密码设置为空,当检测到密码为空的时候就用不带密码的语句),注意把原来字符串替换成变量的写法,选出来之后替换成两个双引号,然后再在中间加两个空格,再在空格中加变量名,这样不容易出错,连接成功或者失败也是布尔值对外返回。
为了让代码更加整洁,对一个题目所包含的全部信息,我们都做成一个结构体(这个结构体要跟数据库对应起来),这个数据库增加方法就比较简洁,只需要传入一个自定义类型即可
在点击录入按钮的时候,首先实例化一个结构体,然后执行具体函数,为了测试方便可以随便录入几个数据(我们可以从数据库更精简的角度出发,如果问题类型保存原模原样的字符串"判断题","选择题","简答题",那么同样的一条记录会耗费更多的存储空间,所以在真正的数据库设计中都需要把每个字段设计的尽可能简洁)
把数据录入的方法也做成函数的方式,注意传入的是一个结构体类型(这个结构体就对应一条记录,以后一种数据库文件的读写对应一种结构体,也对应一种方法这样做比较好移植和修改)
数据录入其实首先要执行一个数据查询,比如你淘宝注册一个账号,上传一个宝贝,肯定有很多规则限制。账号的用户名不允许非法字符,宝贝的描述不允许有敏感字符等等。我们这里因为只是自己用,所以可以暂时不考虑这些,但是试题编号肯定要求唯一,不然就有缺陷了,没法真正排序得到从小到大的结果了(我们可能还想着1-100题都是判断题,101-200题都是选择题,出题的时候从1-100和101-200都随机出20题这样)
有了数据库内容的录入,就需要考虑修改和删除(当然你直接打开数据库像操作Excel一样也是一种方法,但是不推荐这么做),在做页面之前需要注意,我们用了一个tabcontrol来更好的管理整个程序布局,在代码上也要划区域,不要搞得很乱,所有跟试题录入相关的方法都放在一起,并用一个region括起来(跟全局的也要分开)
整个试题查看的界面设计如下,为了方便快速查看试题,还需要做上一题/下一题的按钮(或者像很多网页一样显示1-10条,11-20条这种十个记录一次显示,我们都会在下面讲到,在试题查看的时候我们把试题的ID也显示出来了,而在试题录入的时候是没有的,因为只有执行完毕才会生成一个唯一的ID,这里试题查看/修改/删除都是根据这个唯一的ID来的,而不是编号)
在切换到试题查看页面的时候,我们需要遍历数据库得到所有的记录,然后放到comboBox给用户随时选择切换试题(这里写了一个DataBaseQuestionGetALL的方法,就是对数据库的所有记录根据某个字段升序或者降序提取出来,参考前面一章直接把ACCESS读取并放到DataGridView显示的功能,这里我们也用到了类似的功能)
这里我们做了一个List可变数组,把所有记录放在List中,但是其实这样做在真实的项目中还是会有问题,比如一个淘宝商品有太多属性,商品描述包含的图片,文字信息有几千个字符,你一条记录就很大,几十万条几百万条记录要统统存到一个List里面你程序就卡死了(而实际上我们目的只是要方便用户快速选择试题,所以只列举跟当前试题编号接近的10个题目就行了)
所以就有了"上一题","下一题"的功能需求。比如我要选择试题编号比当前NO大的三条,并且从小到大排序,或者要选择比当前NO小的一条,就可以使用较为复杂的Select语句,你需要 Top X * 并且添加order by XXX, asc或者desc分别表示升序和降序(第一依据是Question_NO的升序,第二依据是ID的升序,因为第一依据不是主键,可能会有重复的Question_NO,或者按试题分数,限制时间排序都不一定是唯一的,如果不唯一这个select语句就可能不按照你的提示选出来指定的记录数,所以最后要再跟一个唯一的主键ID的排序)
修改此题也比较好理解了,注意跟前面一样,传入的是一个结构体类型,修改成功或者失败都有返回值
删除也比较好理解,只不过删除了这一题,为了提高用户体验,还需要直接刷新到下一题(如果真的要做优化还是有很多判断没有做,比如当前就是最后一题,那么就跳到上一题或者第一题,删除之前弹出个确认框之类的)
更多教学视频和资料下载,欢迎关注以下信息:
我的优酷空间:
http://i.youku.com/acetaohai123
我的在线论坛:
http://csrobot.gz01.bdysite.com/
问题交流:
QQ:910358960