Entity Framework saving data in one-to-one associations
Asked Answered
S

1

12

I'm trying to use the foreign key association approach to achieve a one-to-one association in EF. In my case there's an association between a User and a Team, and I need a navigation property in each of them. I bumped into a problem when trying to save data.

This is what the models look like:

public class Team
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int OwnerID { get; set; }
    public virtual User Owner { get; set; }
}

public class User
{
    public int ID { get; set; }
    public string UserName { get; set; }

    public int TeamID { get; set; }
    public virtual Team Team { get; set; }
}

I added these bits to the DbContext OnModelCreating(), as instructed in the blog post referenced above:

modelBuilder.Entity<User>()
    .HasRequired(u => u.Team)
    .WithMany()
    .HasForeignKey(u => u.TeamID);

modelBuilder.Entity<Team>()
    .HasRequired(t => t.Owner)
    .WithMany()
    .HasForeignKey(t => t.OwnerID)
    .WillCascadeOnDelete(false);

And now when adding data like this:

User u = new User();
u.UserName = "farinha";
Team t = new Team("Flour Power");
u.Team = t;
t.Owner = u;
context.Users.Add(u);
context.Teams.Add(t);
context.SaveChanges();

or even like this:

User u = new User();
u.UserName = "farinha";
u.Team = new Team("Flour Power");
context.Users.Add(u);
context.SaveChanges();

I'm getting the following error:

Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.

Any idea of how to solve this? Am I saving the data in a wrong way?

Thanks in advance

Sievers answered 10/5, 2011 at 23:10 Comment(0)
S
14

You are not saving data wrong way but it simply cannot work because you defined bidirectional dependency. Team can be saved only if related to already saved user and user can be saved only if related to existing team. You must make one relation optional by marking foreign key property nullable (for example TeamId in User):

public class User
{
    public int ID { get; set; }
    public string UserName { get; set; }

    public int? TeamID { get; set; }
    public virtual Team Team { get; set; }
}

Then you must save the User entity first and then you can save Team.

User u = new User();
u.UserName = "farinha";
context.Users.Add(u);
context.SaveChanges();

u.Team = new Team { Name = "Flour Power", OwnerID = u.ID };
context.SaveChanges();
Seclusion answered 10/5, 2011 at 23:17 Comment(6)
@ladislav-mrnka That causes the error to change to Cannot insert the value NULL into column 'TeamID', table 'DeuceHigh.dbo.User'; column does not allow nulls. INSERT fails. The statement has been terminated.Sievers
@Sievers Since you model changed, did you database table get updated too?Overt
@Farinha: This is database level error which means that TeamID in the User table is still not nullable. You didn't recreate or modify the database.Seclusion
I have configured EF to drop and recreate the database when the model changes, so the DB is being recreated, which should cause TeamID to be created as nullable. The bit in the DbContext OnModelCreating() could be causing problems, so I changed the User entity to HasOptional(u => u.Team) which now causes "The INSERT statement conflicted with the FOREIGN KEY constraint "Team_Owner". The conflict occurred in database "DeuceHigh", table "dbo.User", column 'ID'"Sievers
I edited my answer. You must manually set OwnerID in the new team because your two relations are independent on each other.Seclusion
That looks right now, but also had to change the bit in the DbContext OnModelCreating() that I mentioned in my comment above. That seems to be the thing that actually causes the DB column to be nullable.Sievers

© 2022 - 2024 — McMap. All rights reserved.