Reputation: 5822
I have this error:
UpdateException: Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.
When I am creating records in a database.
The database (which cannot be changed) has the following structure:
Users
- UserID (PK, FK, int not null) (no identity spec)
Persons
- PersonID (PK, Identity spec)
This is my code:
var user = new User();
user.Username = emailAddresses.First();
user.Password = encryptedPassword;
user.Salt = salt;
user.Active = true;
user.EditedBy = 1;
var role = new User_Roles();
role.UserId = user.UserId;
role.EditedBy = 1;
role.RoleId = 11;
var person = new Person();
user.UserId = person.PersonId;
person.FirstName = firstname;
person.LastName = lastname;
person.MiddleName = middleName;
user.Persons.Add(person);
context.Persons.Add(person);
context.Users.Add(user);
context.User_Roles.Add(role);
context.SaveChanges();
I am using EF 6.2 and not really sure how to get this to work. I used the EDMX approach to create the model from the DB.
It's worth noting that this works fine using EF Core but I cannot use EF Core for this particular area of the project.
Any ideas what to do here? How can I get the User and Person to save without the error? The user is somewhat a self referencing table I suspect.
For the person model, I added the following attribs:
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int PersonId { get; set; }
And for the User model, I added the following:
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
public int UserId { get; set; }
But no avail.
Upvotes: 0
Views: 115
Reputation: 34683
The problem will most likely be:
var person = new Person(); user.UserId = person.PersonId;
Person is an Identity spec, EF won't have an ID here until you call SaveChanges.
The best way to address this is to set up the entity relationships so that EF associates a 1-to-1 relationship between User and Person on the associated ID. I don't recommend mapping a "UserID" to a "PersonID" as that is plain confusing from a data querying perspective. Just give User a PersonId.
For the mapping you can use an EntityTypeConfiguration or map it with the modelBuilder.
eg.
public class PersonConfiguration : EntityTypeConfiguration<Person>
{
public PersonConfiguration()
{
ToTable("Persons");
HasKey(x => x.PersonId)
.Property( x=> x.PersonId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasOne(x => x.User)
.WithRequiredDependency()
.HasForeignKey(x => x.PersonId);
}
}
public class UserConfiguration : EntityTypeConfiguration<User>
{
public PersonConfiguration()
{
ToTable("Users");
HasKey(x => x.PersonId);
}
}
Then when you go to insert the User/Person:
var person = new Person
{
// populate Person details...
User = new User
{
// populate user details... Don't worry about PersonId...
}
}
dbContext.Persons.Add(person);
dbContext.SaveChanges();
User Roles would follow a many-to-many mapping between users and roles. Depending on the schema this can be done with or without a linking entity (UserRole) though generally it's just simpler to use a linking entity so I'd recommend reading on how those are mapped. For things like change-tracking (CreatedAt/CreatedBy etc.) you will need linking entities since entity-less many-to-many joins only support tables with just the 2x FKs, no other columns.
Upvotes: 1