The dependent property in the reference binding maps to the store-generated column error with a 1 to 1 ratio

The first EntityFramework code models have a 1: 1 ratio:

public class Child1 { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public string Name { get; set; } public Child2 Child2 { get; set; } } public class Child2 { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] [ForeignKey("Child1")] public int Id { get; set; } public string Name { get; set; } public Child1 Child1 { get; set; } } 

When I tried to insert some data into the database, it threw an exception:

 {"A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'Id'."} 

It seems I can not use the automatically generated identifier for Child2 , how can I save this function and establish a connection between that?

+7
entity-framework ef-code-first
source share
1 answer

There are two problems here, the obvious ones shown in the exception. When you define a one-to-one relationship, FK should also be PK. In this case, PK and FK of both objects are Id fields. The problem indicated by the exception is that FK is a generated database. Thus, if you insert Child1 with the associated Child2 , EF is not able to set the FK value for the associated Child2 , since it generates a database.

A second problem that has not yet arisen is that a one-to-one relationship is only a theoretical thing in a database such as SQL Server. If you want to insert Child1 , which depends on Child2 , you need to insert Child1 first, and then the associated Child2 . That's right, but, ooops, you should also insert Child2 before inserting Child1 , because Child1 also depends on Child2 . Thus, a pure one-to-one relationship is not possible.

To solve this problem, you need to do two things:

  • make the ratio 1-to- (0 or 1). That is, you must have a main object and a dependent object that may or may not exist. This will allow you to insert the main entity without a dependent object, because with this configuration you can initialize a principal without a dependent.
  • the main PK can be left as the generated database, but you must change the PK to a dependent object so that it is not generated by db. That way, when you insert a dependent object, PK, which is also an FK, can be freely specified by EF.

Finally, if you think about it, a 1 to 1 relationship usually doesn't make sense. You can use one table that contains all the columns in both tables, because when a row exists in table A, it must exist in table B and vice versa. Thus, having one table has the same effect.

However, if you still want to use the 1-to-1 relationship, EF allows you to model it like this:

 modelBuilder.Entity<Child1>() .HasRequired(c1 => c1.Child2) .WithRequiredPrincipal(c2 => c2.Child1); 

Please note that in this case, the EF abstraction allows you to have a 1 to 1 relationship, even if it cannot exist in the database. However, you must specify this relationship using ModelBuilder , because you need to specify the main and dependent side. In this case, the principle is Child1 , and the dependent is Child2 . Note that you should still be careful with the rule for generated database values.

NOTE that this is modeled in a database with one FK from Child2 to Child1 , and not FK from Child1 to Child2 . Thus, in the database there is a relation (1) -to (0 or 1), as described above

 public class Child1 { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] // Leave as is public int Id { get; set; } ... public class Child2 { //[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.None)] // Not db-generated //[ForeignKey("Child1")] -- specified in the model builder public int Id { get; set; } 
+21
source share

All Articles