Reputation: 1179
After changing relationship of Question and PossibleAnswer from Many-to-many to One-to-many I got an exception: "The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: Multiplicity constraint violated. The role 'PossibleAnswer_Question_Source' of the relationship 'WebUI.Models.PossibleAnswer_Question' has multiplicity 1 or 0..1." What does it mean?
Here is my model:
public class Question
{
public int ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
public virtual ICollection<PossibleAnswer> PossibleAnswers { get; set; }
public virtual ICollection<Results> Results { get; set; }
}
public class PossibleAnswer
{
public int ID { get; set; }
public string Text { get; set; }
public virtual Question Question { get; set; }
}
And view model for Question (I know that ToQuestion should be in controller, I will rearrange it later):
public class QuestionVM
{
public QuestionVM() {
}
public QuestionVM(Question question) : this()
{
ID = question.ID;
Text = question.Text;
IsAssociatedWithProfessor = question.IsAssociatedWithProfessor;
IsAssociatedWithAssistant = question.IsAssociatedWithAssistant;
}
public int? ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
private IEnumerable<string> _possibleAnswers;
public IEnumerable<string> PossibleAnswers
{
get
{
return _possibleAnswers ?? new List<string>(){"", "", "", "", ""};
}
set
{
_possibleAnswers = value;
}
}
public Question ToQuestion()
{
Question question = new Question
{
Text = this.Text,
IsAssociatedWithProfessor = this.IsAssociatedWithProfessor,
IsAssociatedWithAssistant = this.IsAssociatedWithAssistant,
PossibleAnswers = new List<PossibleAnswer>()
};
//ID will be null if creating new question
if(ID != null)
{
question.ID = (int) ID;
}
foreach (string possibleAnswer in this.PossibleAnswers)
{
if (!String.IsNullOrEmpty(possibleAnswer))
{
question.PossibleAnswers.Add(new PossibleAnswer { Text = possibleAnswer });
}
}
return question;
}
}
Here is my post method for creating new question:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddQuestion(QuestionVM questionVM)
{
try
{
if (ModelState.IsValid)
{
Question question = questionVM.ToQuestion();
context.Questions.Add(question);
context.SaveChanges();
return RedirectToAction("Questions");
}
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Trenutno nije moguće snimiti promjene, pokušajte ponovo.");
}
return View(questionVM);
}
Line:question.PossibleAnswers.Add(new PossibleAnswer { Text = possibleAnswer });
causes the exception since I didn't save possible answers in database before I am adding them to question... But how can I add them to database without use of DbContext (since it is not a good practice to use DbContext in method which converts view model to model)?
Upvotes: 2
Views: 395
Reputation: 6766
Error is coming because PossibleAnswers are not being marked as added entity.
So update your QuestionVM like below:
public class QuestionVM
{
public QuestionVM() {
}
public QuestionVM(Question question) : this()
{
ID = question.ID;
Text = question.Text;
IsAssociatedWithProfessor = question.IsAssociatedWithProfessor;
IsAssociatedWithAssistant = question.IsAssociatedWithAssistant;
}
public int? ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
private IEnumerable<string> _possibleAnswers;
public IEnumerable<string> PossibleAnswers
{
get
{
return _possibleAnswers ?? new List<string>(){"", "", "", "", ""};
}
set
{
_possibleAnswers = value;
}
}
public Question ToQuestion()
{
Question question = new Question
{
Text = this.Text,
IsAssociatedWithProfessor = this.IsAssociatedWithProfessor,
IsAssociatedWithAssistant = this.IsAssociatedWithAssistant,
PossibleAnswers = new List<PossibleAnswer>()
};
//ID will be null if creating new question
if(ID != null)
{
question.ID = (int) ID;
}
return question;
}
public List<PossibleAnswer> GetPosibleAnswers()
{
var listOfPossibleAnswers = new List<PossibleAnswer>();
foreach (string possibleAnswer in this.PossibleAnswers)
{
if (!String.IsNullOrEmpty(possibleAnswer))
{
listOfPossibleAnswers.Add(new PossibleAnswer { Text = possibleAnswer });
}
}
return listOfPossibleAnswers;
}
}
and then update your code like below.
if (ModelState.IsValid)
{
Question question = questionVM.ToQuestion();
context.Questions.Add(question);
context.SaveChanges();
question.PossibleAnswers.AddRange(questionVM.GetPosibleAnswers());
context.SaveChanges();
return RedirectToAction("Questions");
}
Upvotes: 1