I’m using ASP.Net MVC3, and Entity Framework 4.
Employee has an OfficeLocation, which is in another table for normalization.
I have a new Employee screen, with a drop down for Office Location:
<div class="editor-label">
@Html.LabelFor(model => model.OfficeLocation.Id, "Office Location")
</div>
<div class="editor-field">
@Html.DropDownListFor(model => model.OfficeLocation.Id, new SelectList(ViewBag.OfficeLocations, "Id", "Name"))
@Html.ValidationMessageFor(model => model.OfficeLocation.Id)
</div>
It points at the Id because I was having trouble getting the binding to work. In my controller, I load the OfficeLocation from the database, and store it back in my new Employee before saving. I’ve inspected the values at this point and everything is correct. I’ve also tried to Attach() employee.OfficeLocation, with no change. employee.OfficeLocation has no null values in it, and its state is Unchanged.
employee.OfficeLocation = db.OfficeLocations.Single(d => d.Id == employee.OfficeLocation.Id);
db.Employees.AddObject(employee);
db.SaveChanges();
And that’s when I get an exception about inserting into OfficeLocations:
Cannot insert the value NULL into column 'Name', table 'test.HR.OfficeLocations'; column does not allow nulls. INSERT fails.
The statement has been terminated.
I’ve also tried the usual restarting Visual Studio, cleaning the build, et cetera.
Update: When I allowed null values, I found that it inserted a row into OfficeLocation with all null values, and then it used the correct value in the Employee table. What.
The root cause of my problem was that in working around IModelBinder, I was causing something in the framework to generate new OfficeLocations that only contained an (existing) Id – which is ignored by EF when inserting, because I have it using SQL’s Id generation. I worked this out by letting the columns be null and noticing that it correctly set the existing Id in the Employee table, while inserting a new, null-Named record into the other table.
So even though that new Entity was no longer referenced anywhere, the framework was trying to insert it when I saved the Employee entity that originally referenced it.
Hopefully someone else will benefit from this.