I'm having great difficulties with creating a complex object. I have an EF model with a Consultant table that has one-to-many relationships to a number of other tables. I wanted to use the Consultant object as the model as is because it would be very simple and easy (and as it's done in the NerdDinner tutorial), as I've done with other objects that didn't have one-to-many relationships. The problem is that these relationships cause this error: "EntityCollection already initialized" when I try to post to the Create method.
Several people have advised me to use a ViewModel instead, and I posted a question about this (ViewModels and one-to-many relationships with Entity Framework in MVC?) because I don't really understand it. The problem is the code gets reeeeally ridiculous... It's a far cry from the simplicity I've so far appreciated in MVC.
In that question I forgot to mention that besides the Create method, the Edit method uses the same CreateConsultant method (the name may be misleading, it actually populates the Consultant object). And so in order not to have additional, say "Programs" added when editing, I needed to complicate that method further. So now it looks like this:
private Consultant CreateConsultant(ConsultantViewModel vm, Consultant consultant) //Parameter Consultant needed because an object may already exist from Edit method.
{
consultant.Description = vm.Description;
consultant.FirstName = vm.FirstName;
consultant.LastName = vm.LastName;
consultant.UserName = User.Identity.Name;
if (vm.Programs != null)
for (int i = 0; i < vm.Programs.Count; i++)
{
if (consultant.Programs.Count == i)
consultant.Programs.Add(vm.Programs[i]);
else
consultant.Programs.ToList()[i] = vm.Programs[i];
}
if (vm.Languages != null)
for (int i = 0; i < vm.Languages.Count; i++)
{
if (consultant.Languages.Count == i)
consultant.Languages.Add(vm.Languages[i]);
else
consultant.Languages.ToList()[i] = vm.Languages[i];
}
if (vm.Educations != null)
for (int i = 0; i < vm.Educations.Count; i++)
{
if (consultant.Educations.Count == i)
consultant.Educations.Add(vm.Educations[i]);
else
consultant.Educations.ToList()[i] = vm.Educations[i];
}
if (vm.WorkExperiences != null)
for (int i = 0; i < vm.WorkExperiences.Count; i++)
{
if (consultant.WorkExperiences.Count == i)
consultant.WorkExperiences.Add(vm.WorkExperiences[i]);
else
consultant.WorkExperiences.ToList()[i] = vm.WorkExperiences[i];
}
if (vm.CompetenceAreas != null)
for (int i = 0; i < vm.CompetenceAreas.Count; i++)
{
if (consultant.CompetenceAreas.Count == i)
consultant.CompetenceAreas.Add(vm.CompetenceAreas[i]);
else
consultant.CompetenceAreas.ToList()[i] = vm.CompetenceAreas[i];
}
string uploadDir = Server.MapPath(Request.ApplicationPath) + "FileArea\\ConsultantImages\\";
foreach (string f in Request.Files.Keys)
{
var filePath = Path.Combine(uploadDir, Path.GetFileName(Request.Files[f].FileName));
if (Request.Files[f].ContentLength > 0)
{
Request.Files[f].SaveAs(filePath);
consultant.Image = filePath;
}
}
return consultant;
}
This is absurd, and it's probably due to my incompetence, but I need to know how to do this properly. Just the answer "use a ViewModel" obviously won't suffice, because that's what got me into this trouble to begin with. I want the simplicity of the simple entity object as model but without the "EntityCollection has already been initialized" error. How do I get around this?
Of course, if I'm just doing the ViewModel strategy the wrong way, suggestions on that are welcome too, but mainly I want to know what is causing this error if I do it the simple "NerdDinner" simple object way. Please keep in mind also that the View in question is restricted to authorized users of the site. I would love to do it the "correct" way, but if using ViewModels implies having code that is this hard to maintain, I'll forgo it...
Please help!
UPDATE:
Turns out this code doesn't even work. I just checked after calling Edit to update values, and it doesn't update them. So only the Create part works.
This is the part that doesn't work:
consultant.Programs.ToList()[i] = vm.Programs[i];
I sort of had a hunch I couldn't use ToList and update an item in the EntityCollection. But this makes it even harder. So now I don't know how to do it with the entity directly, which I would prefer (see above). And I don't know how to get this ViewModel stuff working, let alone get it clean...
Any ideas? There must be something really wrong here, and I'm hoping someone will spot how I've just missed something simple that turns all of this code on its head!