Entity Framework вставляет подсписок в родительский подсписок - PullRequest
0 голосов
/ 27 марта 2020

Я пытаюсь вставить список Answers в Questions, который в свою очередь вставляется в Exams, весь мой код работает нормально, кроме одной части, которая вставляет новый Answers.

Данные вставляются просто отлично, за исключением данных Ответов, данные которых не хранятся в базе данных, плюс я пытаюсь получить QuestionId, чтобы я мог сохранить его с Ответом как внешний ключ, и мне тоже не удалось это сделать.

API-контроллер

        public IActionResult addExam([FromBody] Exams exam)
        {
            try
            {
                if (exam == null)
                {
                    return StatusCode(401, "data is null");
                }

                var userId = this.help.GetCurrentUser(HttpContext);


                Exams exams = new Exams
                {
                    Name = exam.Name,
                    Number = exam.Number,
                    FullMarck = exam.FullMarck,
                    CreatedBy = userId,
                    CreatedOn = DateTime.Now,
                    Status = exam.Status
                };
               db.Exams.Add(exams);

                var questionsList = new List<Questions>();

                foreach (Questions item in exam.Questions)
                {
                    var question = new Questions
                    {

                        ExamId = exam.Id,
                        Points = item.Points,
                        CreatedBy = userId,
                        CreatedOn = DateTime.Now,
                        Status = item.Status,
                    };
                    questionsList.Add(question);

                }

               exams.Questions = questionsList;
                db.SaveChanges();
                foreach (Questions item in exam.Questions)
                {

                    var answersList = new List<Answers>();
                    foreach (Answers answers in item.Answers)

                        answersList.Add(new Answers
                        {
                            QuestionId = item.Id,
                            ExamAnswers = answers.ExamAnswers,
                            CreatedBy = userId,
                            CreatedOn = DateTime.Now
                        });
                    item.Answers = answersList;

                }

                db.SaveChanges();
                return Ok("successfully created ");
            }
            catch (Exception e)
            {
                return StatusCode(500, e.InnerException.Message);
            }

        }

Ответы [ 4 ]

1 голос
/ 27 марта 2020

То, как вы строите свой график, немного необычно. Я ожидал бы, что это больше похоже на один набор вложенных циклов, который использует вашу предоставленную модель и заполняет коллекции сущностей без принудительных идентификаторов. EF будет отслеживать идентификаторы; вам не нужно беспокоиться о них; когда вы добавляете новый ответ на конкретный вопрос. В коллекции ответов вам не нужно указывать ответу, каков его вопрос. EF знает, на основании какого вопроса он был добавлен. Если идентификатор вопроса еще не установлен, так как он сгенерирован базой данных, а сохранение не произошло, то при сохранении вопроса будет сгенерирован идентификатор, а EF сгладит изменения во всех принадлежащих ответах в вопросе. Ответы; вам не нужно микро управлять этим

Вот псевдокод того, как я ожидал бы, что go:

//model is an ExamModel

Exam e = new Exam(); //exam is a db entity
e.Title = model.ExamTitle; //model is not a db entity

foreach(QuestionModel mq in model.Questions){ //enumerate all the questionmodel we got from the front end and build a db entity graph 

  Question q = new Question(); //make new db entity

  q.Subject = mq.QuestionHeader; //set entity property from model
  q.Body = mq.BodyText; //set property from model

  if(e.Questions == null) //not sure how your entities are declared, if this is already done elsewhere, remove it
    e.Questions = new List<Question>();

  e.Questions.Add(q); //add the question db entity to the exam db entity

  //notice I didn't set the question id. EF will do that- it knows what exam this question belongs to

  foreach(AnswerModel ma in mq.Answers){ //while our question db entity called q is still in scope let us add the related answers to it

    Answer a = new Answer(); //create EF entity
    a.Text = ma.AnswerText; //set db entity property from model property

    if(q.Answers == null)
      q.Answers = new List<Answer>();

    q.Answers.Add(a); //add the answer to the question db entity 
  }

}
//exam e now has a collection of questions that have each a collection of answers, save it to the db 
db.Exams.Add(e);
db.SaveChanges(); //only need one call to save changes on the whole graph

Я думаю, как вы разделите свои операции не создал связанный граф сущностей и / или способ, которым вы задавали вопросы с ответами, означает, что EF не сохранил отношения до даты после сохранения.

У вас также должно быть разделение между объектами данных, поступающими в ваш контроллер (я назвал их ModelExam, ModelQuestion, ModelAnswer) и сущностями в вашем EF (я назвал эти экзамен, вопрос, ответ - у вас множественное число). Это разделение достигается за счет использования других классов для ваших внешних контроллеров и т. Д. c, чем используемый вашим внутренним контекстом БД. Сначала кажется, что вещи повторяются без веской причины, но в конечном итоге система станет достаточно сложной, так что не каждое свойство БД может или должно быть открыто для внешнего интерфейса и обратно, а внешний интерфейс может нуждаться в вычислении или другом не основанные на БД данные. На этом этапе вам действительно нужно, чтобы ваши внешние модели данных были полностью отделены от ваших внутренних данных

0 голосов
/ 27 марта 2020

item.Answers = answersList; является ложным экзаменом. Вопросы. Ответы = ответы. Список истинен.

0 голосов
/ 27 марта 2020

Удалить первую db.SaveChanges(); ведьму до последней foreach l oop. Это вставит все ваши данные сразу и должно выполнить работу.

0 голосов
/ 27 марта 2020

Я думаю, вам нужно вызвать db.SaveChanges () после добавления нового экзамена. В вашем случае идентификатор экзамена не генерируется автоматически и всегда равен 0, поэтому вы не можете сохранить вопрос с экзаменом 0;

...