@stationfuk

Как правильно организовать БД?

Добрый день.

Разрабатываю систему онлайн-тестов на ASP MVC 5, в связи с чем возник по организации базы данных (EF6).
В системе есть тест, в котором есть вопросы. Вопросы можно редактировать, удалять из теста и т.п.

Ситуация 1: тест выдан в состоянии А студентам, после чего был отредактирован в состояние Б. В результате ссылки в результатах теста, ведущие на А становятся неактуальными.
Ситуация 2: из пройденного теста удаляем вопрос. Удалить из базы мы его не можем, т.к. тогда результаты будут неверными, но и не удалить из списка вопросов также не можем, т.к. тогда теряется связь с тестом.

В качестве решения я предполагаю сделать привязку всех сущностей ко времени (т.е. ссылка в результатах теста будет на вопрос с Id=XXX и временем изменения=YYY). Но как быть с удалением - я не понимаю.

Посоветуйте, что тут можно сделать.

public class ExerciseSet
    {
        [Key]
        public string Id { get; set; } = Guid.NewGuid().ToString();

        [Display(Name = "Название")]
        public string Name { get; set; }
        public string Owner { get; set; }

        public virtual List<ExerciseBlock> ExercisesBlocks { get; set; } = new List<ExerciseBlock>();
        public virtual List<GeneratedVariant> GeneratedVariants { get; set; } = new List<GeneratedVariant>();

        [Display(Name = "Примечания")]
        public string Notes { get; set; }

        public ExerciseSet()
        {
        }

        public ExerciseSet(string ownerId)
        {
            Owner = ownerId;
        }

        [NotMapped]
        [Display(Name = "Кол-во заданий")]
        public int ExercisesCount => ExercisesBlocks.SelectMany(x => x.Exercises).Count();
    }

public class ExerciseBlock
    {
        [Key]
        public int Id { get; set; }

        [Display(Name = "Название")]
        public string Name { get; set; }

        public virtual ExerciseSet ExerciseSet {get; set; }

        public virtual List<Exercise> Exercises { get; set; }
    }
public class Exercise
    {
        [Key]
        [HiddenInput(DisplayValue = false)]
        public string Id { get; set; }

        public virtual ExerciseBlock ExerciseBlock { get; set; }

        /// <summary>
        /// Список блоков вопроса, блоки выводятся в соотв. с порядком
        /// </summary>
        [Display(Name = "Блоки вопроса")]
        public virtual IList<Resource> AskBlocks { get; set; }
        /// <summary>
        /// Ответ на вопрос
        /// </summary>
        [Display(Name = "Варианты ответа")]
        public virtual IList<ExerciseAnswer> Answers { get; set; }
        public string AnswerType { get; set; }
        /// <summary>
        /// Подсказка для режима Обучения
        /// </summary>
        [Display(Name = "Подсказка (Обучение)")]
        public string Hint { get;set; }
        /// <summary>
        /// Id тестируемого предмета
        /// </summary>
        [Display(Name = "Предмет")]
        public string Subject { get; set; }
        /// <summary>
        /// Id тестируемой темы
        /// </summary>
        [Display(Name = "Тема")]
        public string Topic { get; set; } = "";

        /// <summary>
        /// Id тестируемого класса
        /// </summary>
        [Display(Name = "Класс")]
        public string Class { get; set; } = "";
        /// <summary>
        /// Id используемого кодификатора
        /// </summary>
        [Display(Name = "Кодификатор")]
        public virtual Codificator Codificator { get; set; }
        public int? CodificatorId { get; set; }
        /// <summary>
        /// Номер проверяемого элемента по кодификатору
        /// </summary>
        [Display(Name = "Элемент кодификатора")]
        public virtual CodificatorSection CodificatorElement { get; set; }
        public int? CodificatorElementId { get; set; }
        /// <summary>
        /// Номер требования к подготовке по кодификатору.
        /// </summary>
        [Display(Name = "Требование кодификатора")]
        public virtual CodificatorSection CodificatorRequirement { get; set; }
        public int? CodificatorRequirementId { get; set; }
        ///// <summary>
        ///// Сложность (базовая, повышенная, высокая)
        ///// </summary>
        //[Display(Name = "Сложность")]
        //public ExerciseBlock Difficulty { get; set; }
        /// <summary>
        /// Время выполнения задания
        /// </summary>
        [Display(Name = "Время на выполнение задания")]
        public TimeSpan Time { get; set; }
        /// <summary>
        /// Кол-во баллов за выполнение задания
        /// </summary>
        [Display(Name = "Количество баллов")]
        public int Points { get; set; }
        /// <summary>
        /// Заметка к заданию
        /// </summary>
        [Display(Name = "Примечания")]
        public string Notes { get; set; }

        public Exercise()
        {
            Id = Guid.NewGuid().ToString();
            AskBlocks = new List<Resource>();
            Answers = new List<ExerciseAnswer>();
        }
    }
  • Вопрос задан
  • 192 просмотра
Пригласить эксперта
Ответы на вопрос 1
sim3x
@sim3x
Тест:
  название
  
ВерсияТеста
  тест = ForeignKey(Тест)
  текст
  дата создания
  автор
  
ВопросТеста
   тест = ForeignKey(ВерсияТеста)
   текст вопроса

ОтветНаВопроТеста
  вопрос теста = ForeignKey(ВопросТеста)


Когда создаешь новую версию - предлагаешь скопировать ВопросТеста из предидущей версии

Версионирование довольно геморное дело и если не нужно строить глубокую аналитику по тестам, то стоит замутить хранение в json'e
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы