3

我在玩 RavenDb,正在做一些测验。有不同类型的问题: - 多项选择(A、B、C 或 D?) - 日期(在什么日期...?) - 数字(多少...?)

我所做的是创建一个带有属性的基类 Question ,Question其中包含用户给出的字符串形式的问题和答案列表。

public class Question
{
    public string Question { get; set; }
    public List<Answer> Answers { get; set; }
}

然后我创建了多个子类,它们继承自Question. 例如,NumberQuestion包含属性MinimumValueMaximumValue,因为这是每个问题的差异。

我希望用户给出答案,并将该答案保存到数据库中。问题是,答案可以是不同的类型,例如 DateTime、float 或 integer(多选)。我的问题是,将答案保存在 RavenDb 中的最佳方法是什么?

这就是我目前正在做的事情:

public class Answer
{
    public User User { get; set; }
    public string AnswerString { get; set; }
    public string AnswerType { get; set; }
}

我在这里所做的是将答案保存为字符串并保存类型(DateTime、float 等),以便稍后解析。

它有效,但我不太喜欢它。必须有另一种更好的方法。

4

2 回答 2

4

如果您想在同一个属性中存储多个类型,则只需将该属性声明为公共基类型。在你的情况下object会做得很好。序列化后,您将在 json 中获得额外的$type字段,这将允许它们被反序列化回正确的形式。

让我们看看我是否可以就您的特定域模型提供一些建议。

  • 不要将可能的答案与实际答案混淆。给这些不同的名称以保持它们的正确性。我将Choice用来表示一个问题的可能答案,并Answer表示用户给出的实际答案。

  • 注意聚合实体的位置。这些是最终在 RavenDB 中作为实际文档并获得 Id 的内容。在你的情况下,我只看到两个 -QuestionExam.

试穿这个尺寸:

public abstract class Question
{
    public string Id { get; set; }
    public string QuestionText { get; set; }
}

public class ValueQuestion : Question
{
    public object CorrectValue { get; set; }
}

public class RangeQuestion : Question
{
    public object MinCorrectValue { get; set; }
    public object MaxCorrectValue { get; set; }
}

public class MultipleChoiceQuestion : Question
{
    public int NumberOfChoicesAllowed { get; set; }
    public List<MultipleChoiceOption> Choices { get; set; }
}

public class MultipleChoiceOption
{
    public char Letter { get; set; }
    public bool Correct { get; set; }
    public object Value { get; set; }
}

public class EssayQuestion : Question
{
    public int MinAnswerLength { get; set; }
    public int MaxAnswerLength { get; set; }
}

public class Exam
{
    public string Id { get; set; }
    public string UserId { get; set; }
    public DateTime Taken { get; set; }
    public decimal Score { get; set; }
    public List<Answer> Answers { get; set; }
}

public class Answer
{
    public string QuestionId { get; set; }
    public bool Correct { get; set; }
    public object Value { get; set; }
}

仿制药可能很诱人,但我想你会发现它们不会给你买太多东西。最后,您的文档中将具有相同的结构,并且在数据库中具有相同的布局。可能唯一的区别是这些$type字段在不同的地方使用。

如果您想尝试基于泛型的解决方案,请尝试以下操作:

public abstract class Question
{
    public string Id { get; set; }
    public string QuestionText { get; set; }
}

public class ValueQuestion<T> : Question
{
    public T CorrectValue { get; set; }
}

public class RangeQuestion<T> : Question
{
    public T MinCorrectValue { get; set; }
    public T MaxCorrectValue { get; set; }
}

public class MultipleChoiceQuestion<T> : Question
{
    public int NumberOfChoicesAllowed { get; set; }
    public List<MultipleChoiceOption<T>> Choices { get; set; }
}

public class MultipleChoiceOption<T>
{
    public char Letter { get; set; }
    public bool Correct { get; set; }
    public T Value { get; set; }
}

public class EssayQuestion : Question
{
    public int MinAnswerLength { get; set; }
    public int MaxAnswerLength { get; set; }
}

public class Exam
{
    public string Id { get; set; }
    public string UserId { get; set; }
    public DateTime Taken { get; set; }
    public decimal Score { get; set; }
    public List<IAnswer> Answers { get; set; }
}

public interface IAnswer
{
    string QuestionId { get; set; }
    bool Correct { get; set; }
}

public class Answer<T> : IAnswer
{
    public string QuestionId { get; set; }
    public bool Correct { get; set; }
    public T Value { get; set; }
}
于 2013-01-22T15:38:10.707 回答
0

你可以使用泛型。创建一个泛型类QuestionTAnswer其中TAnswer必须从抽象类继承Answer。特定的问题类将从该类继承:

public abstract class Question<TAnswer> where TAnswer : Answer
{
    public Guid Id { get; set; }
    public string Question { get; set; }
    public List<TAnswer> Answers { get; set; }
}

public class DateQuestion : Question<DateAnswer>
{
    //...
}

您用于答案的类都继承自基类Answer,基类引用了它所属的问题和回答它的用户。然后,您可以为每种答案类型创建一个单独的表格,从而防止解析类型,同时保持问题、答案和回答它们的用户之间的联系

public abstract class Answer {
    public Guid QuestionId { get; set; }
    public Guid UserId { get; set; }
}

public class MultipleChoiceAnswer :Answer {
    //...
}

public class DateAnswer : Answer {
    //...
}
于 2013-01-22T09:56:09.307 回答