We are using MVC in combination with Entity Framework. At some point we are trying to establish a link between two entities. This works fine in a unit-test, but gives the following error when tried from an MVC controller method:
“An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. “
The (stripped down) classes:
public class Position : Entity
{
public string Function { get; set; }
public Organization Organization{ get; set; }
// public Guid? OrganizationId { get; set; }
// works when enabled!
}
public class Organization: Entity
{
public string Name { get; set; }
public IList<Position> Contacts
{
get {return contacts;}
set { contacts = value; }
}
public class EntityConfiguration :
EntityConfigurationBase<Organization>
{
public EntityConfiguration()
{
HasMany(p => p.Contacts)
.WithOptional(y => y.Organization)
}
}
private IList<Position> contacts = new List<Position>();
}
The (stripped down) controller method that fails:
[HttpPost]
public ActionResult Edit(Position position, string organizationId = "")
{
if (!ModelState.IsValid)
{
return View(position);
}
db.Entry(position).State = EntityState.Modified;
if (!string.IsNullOrEmpty(organizationId))
{
Guid orgId = Guid.Parse(organizationId);
Organization organization =
db.Organizations
.First(x => x.Id.Equals(orgId));
position.Organization = organization;
}
db.SaveChanges();
RedirectToAction("Index");
}
The unit test that passes:
[TestMethod]
public void LinkOrganizationToPositionTest()
{
// arrange
DbModel dbModel;
Organization org;
Position pos;
Guid orgId;
using (dbModel = new DbModel())
{
dbModel.Database.Delete();
dbModel.Database.Create();
// - first organization
org = dbModel.Organizations.Create();
org.Name = "TestOrgFirst";
dbModel.Entry(org).State = EntityState.Added;
pos = dbModel.Positions.Create();
pos.Function = "TestFunc";
dbModel.Entry(pos).State = EntityState.Added;
// - link pos to first org
pos.Organization = org;
org = dbModel.Organizations.Create();
org.Name = "TestOrgSecond";
dbModel.Entry(org).State = EntityState.Added;
orgId = org.Id;
dbModel.SaveChanges();
}
// act
// - obtain "fresh" model
using (dbModel = new DbModel())
{
// - get second org
org = dbModel.Organizations.Find(orgId);
pos = dbModel.Positions.Find(pos.Id);
pos.Organization = org;
dbModel.SaveChanges();
}
// assert
using (dbModel = new DbModel())
{
Position actual =
dbModel.Positions
.Include("Organization")
.First(x => x.Id.Equals(pos.Id));
// - link was saved
Assert.AreEqual(
"TestOrgSecond",
actual.Organization.Name
);
}
}
Why is the is the OrganizationId foreign key property required by the MVC? Is there a simple fix that doesn’t require all the foreign-keys in the model?