Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One to one optional relationship using Entity Framework Fluent API

We want to use one to one optional relationship using Entity Framework Code First. We have two entities.

public class PIIUser {     public int Id { get; set; }      public int? LoyaltyUserDetailId { get; set; }     public LoyaltyUserDetail LoyaltyUserDetail { get; set; } }  public class LoyaltyUserDetail {     public int Id { get; set; }     public double? AvailablePoints { get; set; }      public int PIIUserId { get; set; }     public PIIUser PIIUser { get; set; } } 

PIIUser may have a LoyaltyUserDetail but LoyaltyUserDetail must have a PIIUser. We tried these fluent approach techniques.

modelBuilder.Entity<PIIUser>()             .HasOptional(t => t.LoyaltyUserDetail)             .WithOptionalPrincipal(t => t.PIIUser)             .WillCascadeOnDelete(true); 

This approach didn't create LoyaltyUserDetailId foreign key in PIIUsers table.

After that we tried the following code.

modelBuilder.Entity<LoyaltyUserDetail>()             .HasRequired(t => t.PIIUser)             .WithRequiredDependent(t => t.LoyaltyUserDetail); 

But this time EF didn't create any foreign keys in these 2 tables.

Do you have any ideas for this issue? How can we create one to one optional relationship using entity framework fluent api?

like image 462
Ilkay Ilknur Avatar asked Aug 14 '13 19:08

Ilkay Ilknur


People also ask

How will you create relationship between tables in Entity Framework?

You can create such a relationship by defining a third table, called a junction table, whose primary key consists of the foreign keys from both table A and table B.

How do you create a foreign key relationship in code first approach?

To create Foreign Key, you need to use ForeignKey attribute with specifying the name of the property as parameter. You also need to specify the name of the table which is going to participate in relationship. I mean to say, define the foreign key table. Thanks for reading this article, hope you enjoyed it.


1 Answers

EF Code First supports 1:1 and 1:0..1 relationships. The latter is what you are looking for ("one to zero-or-one").

Your attempts at fluent are saying required on both ends in one case and optional on both ends in the other.

What you need is optional on one end and required on the other.

Here's an example from the Programming E.F. Code First book

modelBuilder.Entity<PersonPhoto>() .HasRequired(p => p.PhotoOf) .WithOptional(p => p.Photo); 

The PersonPhoto entity has a navigation property called PhotoOf that points to a Person type. The Person type has a navigation property called Photo that points to the PersonPhoto type.

In the two related classes, you use each type's primary key, not foreign keys. i.e., you won't use the LoyaltyUserDetailId or PIIUserId properties. Instead, the relationship depends on the Id fields of both types.

If you are using the fluent API as above, you do not need to specify LoyaltyUser.Id as a foreign key, EF will figure it out.

So without having your code to test myself (I hate doing this from my head)... I would translate this into your code as

public class PIIUser {     public int Id { get; set; }         public LoyaltyUserDetail LoyaltyUserDetail { get; set; } }  public class LoyaltyUserDetail {     public int Id { get; set; }     public double? AvailablePoints { get; set; }         public PIIUser PIIUser { get; set; } }  protected override void OnModelCreating(DbModelBuilder modelBuilder) {   modelBuilder.Entity<LoyaltyUserDetail>()   .HasRequired(lu => lu.PIIUser )   .WithOptional(pi => pi.LoyaltyUserDetail ); } 

That's saying LoyaltyUserDetails PIIUser property is required and PIIUser's LoyaltyUserDetail property is optional.

You could start from the other end:

modelBuilder.Entity<PIIUser>() .HasOptional(pi => pi.LoyaltyUserDetail) .WithRequired(lu => lu.PIIUser); 

which now says PIIUser's LoyaltyUserDetail property is optional and LoyaltyUser's PIIUser property is required.

You always have to use the pattern HAS/WITH.

HTH and FWIW, one to one (or one to zero/one) relationships are one of the most confusing relationships to configure in code first so you are not alone! :)

like image 118
Julie Lerman Avatar answered Nov 13 '22 10:11

Julie Lerman