前段时间做考试系统中在线考试部分的功能,需要将考生在线时对试题的作答情况记录下来,参考了一下别人的做法,解决这个问题的思路有两个:一是在数据库中建表,用来保存考生作答时的答案,等考生交卷后再将临时保存考生答题信息的表的数据插入到记录考生答题情况的正式表中;二是不在数据库中用表保存考生交卷前对试题的作答情况,而是将考生交卷前的答题信息保存在文件中,等考生交卷后将记录考生答题情况文件中的信息写入数据库。第一种思路的优点是考生答题过程中的答题情况可以确保更好的正确性,缺点是不能排除与数据库连接发生错误从而导致不能将数据写入的可能,此外,另一个缺点是在线考试时考生较多,如果每答一题就对数据库操作一次,这样频繁地对数据库的访问和操作会增大数据库的压力,有可能导致严重的后果。第二种思路的优点恰恰就是能够避免出现第一种思路的缺点,缺点就是因为考试时答题情况的数据非常重要,记录在文件中则有被窜改的可能。综合考虑客户实施部署考试系统的环境和实际情况之后,决定采用第二种思路。针对第二种思路的缺点,鉴于其网络环境为内部局域网,考生使用的机器配备的输入输出设备有限等情况,其缺点还不足以有多大的概率发发生。而且,客户一再要求在线考试时候,要将一切影响考试正常进行的因素降到最低,尽量减少对数据库的访问,权衡之后决定采用第二种思路。从第二种思路出发,我采用cookie文件来临时保存考生的答题信息这一做法。由于之前没有尝试过这种做法,所以先到网上找了一大通资料,先了解了解。从最初的了解到组后将功能实现,花了大概两三天时间。走了不少弯路,故将其过程记录下,以免日后遇到同样的问题重蹈覆辙。
采用该方法,直至最后交卷,将cookie文件中保存的考生答题信息写入数据库,其优化和合理的流程是:考生登录->创建cookie文件->考生答题->更新cookie文件->继续答题->更新cookie文件->交卷->获取cookie文件答题信息->写入数据库(同时将获取的数据以xml格式文件上传到服务器以备后用)。在这个过程中,对于cookie文件的操作是重点,因为它记录的信息至关重要,更新cookie文件时必须考虑到考生作答的试题是之前就已经在cookie文件里有记录还是第一次对该题作答,如果是第一次作答,则在原cookie文件中加上作答信息即可;如果之前就已经作答过,现在来修改,则必须在cookie文件中找出保存在cookie文件中对应试题的信息进行更新,因为考生每作答一次就必须对cookie文件进行更新,所以特将对cookie文件的更新写成一个方法,这样可以重复调用。
所有的思路和步骤都已经清晰,代码则就是水到渠成的事了,下面是更新cookie的最重要部分代码:
/// <summary>
/// 更新cookie文件内容
/// </summary>
private void UpdateCookie()
{
// 往cookie集合中增加答题信息
int c_timulx = Convert.ToInt32(ViewState["c_timulx"]);// 题目类型
string c_bianhao = Convert.ToString(ViewState["c_bianhao"]);// 试题编号
string cookieID = ViewState["cookieID"].ToString();
string daan = this.GetDaan(c_timulx);// 获取考生答案
// 获取原cookie文件中的内容
string oldCookieValue = "";
if (Request.Cookies[cookieID].Value != null)
{
oldCookieValue = Request.Cookies[cookieID].Value;
}
// 如果原cookie文件中已经存在当前题的答题信息,则取出原cookie文件中的当前题的信息,进行修改
string newCookieValue = "";// 新cookie文件的内容
string newAnswer = "|" + c_timulx.ToString() + "," + c_bianhao;// 当前题在原cookie文件中的内容
if (oldCookieValue.Contains(newAnswer))
{
// 删除原cookie文件
HttpCookie oldCookie = Request.Cookies[cookieID];
oldCookie.Expires = DateTime.Now.AddHours(-1);
Response.Cookies.Add(oldCookie);
// 组装新cookie文件的内容
string[] temp = oldCookieValue.Split(''|'');
foreach (string s in temp)
{
string[] tempDaan = s.Split('','');
string element1 = tempDaan[0];//
string element2 = tempDaan[1];
string element3 = tempDaan[2];
if (c_timulx.ToString() == element1 && c_bianhao == element2)// 如果是编辑曾在cookie中有答案保存的题目
{
newCookieValue = oldCookieValue.Replace("|" + element1 + "," + element2 + "," + element3, "|" + c_timulx.ToString() + "," + c_bianhao + "," + daan);
}
}
}
else// 如果原cookie文件中不存在当前题的答题信息,则往原cookie文件中添加当前题的答案
{
// 删除原cookie文件
HttpCookie oldCookie = Request.Cookies[cookieID];
oldCookie.Expires = DateTime.Now.AddHours(-1);
Response.Cookies.Add(oldCookie);
// 组装新cookie文件的内容
newCookieValue = oldCookieValue + "|" + c_timulx.ToString() + "," + c_bianhao + "," + daan;
}
// 组成新的cookie文件内容,创建cookie对象
HttpCookie objcookie = new HttpCookie(cookieID, newCookieValue);
// 设置cookie文件的生命周期
DateTime now = DateTime.Now;
TimeSpan ts = new TimeSpan(2, 0, 0);// 生命周期设为2个小时
objcookie.Expires = now + ts;
// 设置cookie采用SSL传送方式
//objcookie.Secure = true;
Response.Cookies.Add(objcookie);
}