DbUpdateException with entities that do not expose foreign key properties

ef-code-first, entity-framework, entity-framework-4, entity-framework-4.3

Solution

I feel really dumb right now. After writing up this careful question, it's now obvious.

The `Person` I am testing with already exists, and already has a `User` association with a different `User.Name`. This is why `user` is coming up null. Setting the `Person.User` property to a new `User` is causing the old `User` to be put in the `Deleted` state. Doh.

Sorry to have wasted your time. I'll leave the question up unless it's agreed it would be better to delete it.

Problem

I have an entity model with `User` and `Person` entities, such that each `User` must be associated with exactly 1 `Person`, and each `Person` can be associated zero or 1 `User`. ``` User (0..1) <-------> (1) Person ``` The association is mapped fluently. Originally I only had it declared on the `Person` side: ``` private class PersonOrm : EntityTypeConfiguration<Person> { internal PersonOrm() { ToTable(typeof(Person).Name, DbSchemaName.People); // has zero or one User HasOptional(p => p.User) .WithRequired(d => d.Person) .Map(d => d.MapKey("PersonId")) .WillCascadeOnDelete(false) ; ``` Since I encountered this error, I also added the same mapping to the `User` side: ``` private class UserOrm : EntityTypeConfiguration<User> { internal UserOrm() { ToTable(typeof(User).Name, DbSchemaName.Identity); // has exactly 1 Person HasRequired(p => p.Person) .WithOptional(d => d.User) .Map(d => d.MapKey("PersonId")) .WillCascadeOnDelete(false); ``` There is a scenario in the application where a new `User` can be created and associated with an existing `Person`. This is where I am having difficulty at the moment. EF is considering `User` as the dependent side of the relationship, and is putting a `PersonId (FK, int, not null)` column on the `User` table. I don't believe it's possible to use a foreign key property on either entity to help EF manage the association (is it?). Here is some failing code that tries to handle the scenario: ``` // find out if Person already exists var person = context.People.SingleOrDefault(p => p.Emails.Any( e => e.Value.Equals(emailAddress, StringComparison.OrdinalIgnoreCase))); // find out if User already exists var user = context.Users.SingleOrDefault( u => u.Name.Equals(emailAddress, StringComparison.OrdinalIgnoreCase)); if (user == null) { user = new User { Name = emailAddress, IsRegistered = isRegistered, Person = person ?? PersonFactory.Create(emailAddress), // ignore the PersonFactory.Create, that part works }; context.Entry(user).State = EntityState.Added; context.SaveChanges(); } ``` This code works fine when `person` is null (does not already exist in the db). However when `person` is not null (already exists in db) and `user` is null, the code attempts to create a new `User` and associate it with the existing `Person`. When invoking `SaveChanges()`, I get a `DbUpdateException`: 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. See the InnerException for details. The inner exception is: A relationship from the 'User_Person' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'User_Person_Source' must also in the 'Deleted' state. This doesn't make any sense to me because I'm not trying to delete anything, and checking the `EntityState` of both `User` and `Person` shows that `User` is in the `Added` state, whereas `Person` is in the `Unchanged` state. I have overridden `SaveChanges()` to demonstrate: ``` public override int SaveChanges() { var userChanges = ChangeTracker.Entries<User>().Single(); var personChanges = ChangeTracker.Entries<Person>().Single(); if (userChanges.State == EntityState.Deleted) throw new InvalidOperationException("wtf?"); if (personChanges.State == EntityState.Deleted) throw new InvalidOperationException("wtf?"); return base.SaveChanges(); } ``` When this code executes, neither `InvalidOperationException` is thrown. Again, `userChanges` is in the `Added` state, and `personChanges` is in the `Unchanged` state. What am I doing wrong?

Original source