I have an entity model with User
and Person
objects, so each User
must be associated with exactly 1 Person
, and each Person
can be associated with zero or 1 User
.
User (0..1) <-------> (1) Person
Communication is matched seamlessly. Initially, I only declared this on the Person
side:
private class PersonOrm : EntityTypeConfiguration<Person> { internal PersonOrm() { ToTable(typeof(Person).Name, DbSchemaName.People);
Since I ran into 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);
The application has a script in which you can create a new User
and associated with an existing Person
. At the moment I am having difficulty. EF treats User
as the dependent side of the relationship and puts the PersonId (FK, int, not null)
column in the User
table. I don't find it possible to use a foreign key property for any object to help EF manage the association (is this?).
Here are some unsuccessful codes that try to process the script:
// 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 (it does not exist in db yet). However, when Person
not null (already exists in db) and User
is null, the code tries to create a new User
and associate it with an existing Person
. When calling SaveChanges()
I get a DbUpdateException
:
An error occurred while saving objects that do not display the property foreign key for their relationships. The EntityEntries property will return null because a single object cannot be identified as the source of the exception. Exception handling during saving can be performed easier by exposing the foreign key properties in its object types. See InnerException for details.
Internal exception:
Relations from the 'User_Person' AssociationSet are in the Deleted State. Given the limitations of multiplicity, the corresponding 'User_Person_Source' must also be in the "Deleted" state.
This makes no sense to me, because I'm not trying to delete anything, and checking the EntityState
both User
and Person
shows that User
is in the Added
state while Person
is in the Unchanged
state. I 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 is executed, no InvalidOperationException
is thrown. Again, userChanges
is in the Added
state, and personChanges
is in the Unchanged
state.
What am I doing wrong?