I'm having problems in understanding how to add objects inside an Entity. I'm using CodeFirst to create models. I have this simplified situation:
public class Question
{
public int QuestionId { get; set; }
public string QuestionText { get; set; }
public List<Answer> Answers { get; set; }
public Question()
{
Answers = new List<Answer>();
}
}
public class Answer
{
public int AnswerId { get; set; }
public int QuestionId { get; set; }
public string AnswerText { get; set; }
public virtual Question Question { get; set; }
}
I have generated a normal controller with read/write actions and views. The form for inserting a collection of Answers isn't generated, but I know it's normal. So I have edited the Create.cshtml file to insert:
Everyone I asked has given me the same link. But this link is obsolete and not related to my problem.
My Question object contains Answer objects and I want to create the inner answers while I'm creating the Question. In the same form. (and without AJAX or JS).
Ok. What you are suggesting was my first attempt to make it work.
The List is being correctly passed to the controller, so the binding name convention is correctly set.
The problem is that the List<Answer> inside my Question entity is never written. Even if I force it with
question.Answers = answers. Later, when I go to get the question from the database, it's always an empty list :(
Not sure if this is the best approach but I have handled this with a different approach.
For each of the answers that are passed in I create and answer object and set its question (not questionid) to the question object and add it to my context
then lastly add the question object to the context and perform the EF save only once. Behind the scenes it will bind the id fo the question object to the questionid field. But this will only work if you perform the save only after adding the answers and
questions to the context instance. If you attempt to save between the answer additions and question addition it will not map the ids correctly and produce sql errors.
I was ready to make a statue of you in my garden... but unfortunately this doesn't work! I'm so sad because I can't understand why on earth the list of answers isn't saved.
This is exactly what I do:
[HttpPost]
public ActionResult Create(Question question)
{
if (ModelState.IsValid)
{
Answer a = new Answer { QuestionId = question.QuestionId, Question = question, AnswerText = "Albert" };
db.Answers.Add(a);
question.Answers = new List<Answer>();
question.Answers.Add(a);
db.Questions.Add(question);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(question);
}
It simply doesn't work. The question and all its properties are saved in the database. But later, I want to get the Question with the Answers. This is my controller:
daliz
Member
8 Points
6 Posts
Create an item that contains a collection
Feb 24, 2012 04:39 PM|LINK
Hello,
I'm having problems in understanding how to add objects inside an Entity. I'm using CodeFirst to create models. I have this simplified situation:
public class Question { public int QuestionId { get; set; } public string QuestionText { get; set; } public List<Answer> Answers { get; set; } public Question() { Answers = new List<Answer>(); } }public class Answer { public int AnswerId { get; set; } public int QuestionId { get; set; } public string AnswerText { get; set; } public virtual Question Question { get; set; } }I have generated a normal controller with read/write actions and views. The form for inserting a collection of Answers isn't generated, but I know it's normal. So I have edited the Create.cshtml file to insert:
I have also modified Details.cshtml so I can see if the Answers have been inserted:
<div class="display-label">Answer</div> <div class="display-field"> @Html.DisplayFor(model => model.Answers[0]) </div>Finally, I have edited my controller to accept a List<Answer> object:
[HttpPost] public ActionResult Create(Question question, List<Answer> answers) { if (ModelState.IsValid) { db.Questions.Add(question); db.SaveChanges(); return RedirectToAction("Index"); } return View(question); }The result is always an empty list. The Answers aren't being put in the database.
So, I think model binding isn't working correctly.
Can anybody please help me in understanding what I'm doing wrong?
Thanks.
ignatandrei
All-Star
134843 Points
21605 Posts
Moderator
MVP
Re: Create an item that contains a collection
Feb 25, 2012 02:51 AM|LINK
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
daliz
Member
8 Points
6 Posts
Re: Create an item that contains a collection
Feb 25, 2012 10:14 AM|LINK
Everyone I asked has given me the same link. But this link is obsolete and not related to my problem.
My Question object contains Answer objects and I want to create the inner answers while I'm creating the Question. In the same form. (and without AJAX or JS).
Thanks.
jerryjoseph
Contributor
6740 Points
1257 Posts
Re: Create an item that contains a collection
Feb 25, 2012 11:14 AM|LINK
Try this.
[HttpPost] public ActionResult Create(Question question, List<Answer> answers) { if (ModelState.IsValid) { question.Answers = answers; db.Questions.Add(question); db.SaveChanges(); return RedirectToAction("Index"); } return View(question); }If it doesn't work then put a break point in the action and see what happens.
linkedin | twitter | www.jerryjoseph.net
daliz
Member
8 Points
6 Posts
Re: Create an item that contains a collection
Feb 25, 2012 12:00 PM|LINK
Ok. What you are suggesting was my first attempt to make it work.
The List is being correctly passed to the controller, so the binding name convention is correctly set.
The problem is that the List<Answer> inside my Question entity is never written. Even if I force it with question.Answers = answers. Later, when I go to get the question from the database, it's always an empty list :(
jerryjoseph
Contributor
6740 Points
1257 Posts
Re: Create an item that contains a collection
Feb 25, 2012 12:11 PM|LINK
Did you check if the parameter answers is not empty inside the Action in the Controller?
linkedin | twitter | www.jerryjoseph.net
daliz
Member
8 Points
6 Posts
Re: Create an item that contains a collection
Feb 25, 2012 12:33 PM|LINK
Yes, I'm sure it is full with the passed data (tried with Debug.Write and with the breakpoint, just to be sure 100%).
skcookie
Member
534 Points
138 Posts
Re: Create an item that contains a collection
Feb 26, 2012 04:13 AM|LINK
Not sure if this is the best approach but I have handled this with a different approach.
For each of the answers that are passed in I create and answer object and set its question (not questionid) to the question object and add it to my context
then lastly add the question object to the context and perform the EF save only once. Behind the scenes it will bind the id fo the question object to the questionid field. But this will only work if you perform the save only after adding the answers and questions to the context instance. If you attempt to save between the answer additions and question addition it will not map the ids correctly and produce sql errors.
Patrick P.
Microsoft Certified Professional
Remember to mark as answer where appropriate!
daliz
Member
8 Points
6 Posts
Re: Create an item that contains a collection
Feb 26, 2012 07:40 PM|LINK
Thank you for your answer, skcookie.
I was ready to make a statue of you in my garden... but unfortunately this doesn't work! I'm so sad because I can't understand why on earth the list of answers isn't saved.
This is exactly what I do:
[HttpPost] public ActionResult Create(Question question) { if (ModelState.IsValid) { Answer a = new Answer { QuestionId = question.QuestionId, Question = question, AnswerText = "Albert" }; db.Answers.Add(a); question.Answers = new List<Answer>(); question.Answers.Add(a); db.Questions.Add(question); db.SaveChanges(); return RedirectToAction("Index"); } return View(question); }It simply doesn't work. The question and all its properties are saved in the database. But later, I want to get the Question with the Answers. This is my controller:
public ViewResult Details(int id) { Question question = db.Questions.Find(id); Debug.WriteLine(question.Answers[0].AnswerText); return View(question); }But a pretty NullReferenceException is raised = the list is empty.
Young Yang -...
All-Star
21345 Points
1818 Posts
Microsoft
Re: Create an item that contains a collection
Mar 02, 2012 05:32 AM|LINK
HI
Please modify this line to:
public virtual ICollection<Answer> Answers { get; set; }If a navigation property can hold multiple entities (as in many-to-many or one-to-many relationships), its type must be ICollection.
Hope this helpful
Regards
Young Yang
Feedback to us
Develop and promote your apps in Windows Store