0

我们有一个网络应用程序,用户可以在其中参加在线考试。

考试管理员将创建一份问卷。一份问卷可以有很多问题。每个问题都是一个选择题 (MCQ)。

假设管理员创建了一个包含 10 个问题的问卷。用户尝试这些问题。现在,与真正的考试不同,用户可以多次尝试单个问卷。我们必须跟踪他的所有尝试。

例如

    User_id     Questionnaire_id    question_id answer  attempt_date    attempt_no
1       1           1       a   1 June 2013 1
1       1           2       b   1 June 2013 1

1       1           1       c   2 June 2013 2
1       1           2       d   2 June 2013 2

现在也可能发生这样的情况,在用户尝试了两次相同的问题后,管理员可以从同一个调查表中删除一个问题,但用户的尝试历史记录仍应参考该问题,以便用户可以在其尝试历史记录中看到他的该问题,尽管管理员删除那个问题。

如果用户现在尝试这个更改后的问卷,他应该只会看到 1 个问题。

    User_id     Questionnaire_id    question_id answer  attempt_date    attempt_no
1       1           1       a   3 June 2013 3

此外,在此用户修改部分问题后,用户尝试历史记录应显示修改前的问题,而任何新尝试都应显示修改后的问题。

我们如何在数据库级别进行管理?

我的第一直觉是,

对于删除,不要进行物理删除,只需使问题处于非活动状态,以便历史记录仍然可以跟踪用户尝试。

对于修改,为问题创建版本,每次新尝试都参考每个问题的最新版本,并在尝试时保留参考问题版本的历史记录。

4

1 回答 1

3

(抱歉,我使用“考试”而不是“问卷”——后者对我的图表来说太笨拙了。)

是的,您必须进行某种形式的版本控制。单独对对象进行版本控制很容易,但是对象之间的版本控制链接可能会很快变得复杂。为了保持它(相对)简单,您可以执行以下操作:

在此处输入图像描述

这形成了一个层次结构,可以根据变化以自下而上的方式进行版本控制:

  • 修改答案文本、添加或删除答案或修改问题文本均被视为对问题的修改。
  • 这与添加或删除问题一起被视为对考试的修改。
  • 这是通过创建一个新的考试版本并在应用适当的更改时复制旧考试版本下的完整树来完成的。

这种版本控制的“分层”方法,即创建整个树的新版本以响应任何树节点的修改,可能有点浪费,但推理和实现相当简单。

另一种方法是显式版本子对象和链接,然后仔细查询,以便只检索特定的“及时快照”。这显然需要一个显着不同的数据库模式......


顺便说一句,您会注意到识别关系和生成的复合主键的巨大用途。这对于正确建模以 USER_ANSWER 为底部的菱形依赖项是必要的,因此用户无法提供不属于考试的答案。

QUESTION.ANSWER_NO 有助于确定正确答案(假设MATCH SIMPLE外键 - 另见这篇文章)。

ATTEMPT.TIMESTAMP 是用户开始尝试的日期/时间。连同给出个人答案的时间,可以重新创建完整的“时间线”。考试时间是从尝试开始到最后一个答案之间的时间。

USER_ANSWER.ANSWER_NO 保留在主键之外,因此不能在同一尝试中为同一问题提供两个不同的答案。

DELETED 标志存在于考试版本中,而不是考试本身,因此如果您取消删除考试,则会有历史记录。您甚至可以多次删除和取消删除同一考试。

于 2013-05-26T20:44:43.927 回答