One to one optional relationship using Entity Framework Fluent API

c# ef-code-first ef-fluent-api entity-framework one-to-one

Accepted Answer

EF Code First is available.1:1 and 1:0..1 relationships. You are seeking for the latter ("one to zero-or-one").

You say necessary on both ends in one instance and both ends can be optional in another instance in your attempts to speak fluently.

On one end, you need optional, and on the other, required.

An illustration from the book Programming E.F. Code First

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

The PersonPhoto navigation property of the entity isPhotoOf it indicates aPerson the kind.Person The navigation property of type isPhoto it indicates thePersonPhoto type.

You use the the first key of each type in the two linked classes, not the overseas keys. Specifically, you won't use theLoyaltyUserDetailId or PIIUserId properties. Rather, the relationship is reliant on theId fields of each kind.

You do not have to specify anything if you are utilizing the fluent API as described above.LoyaltyUser.Id EF will recognize it as a foreign key.

I would transfer this into your code as without having your code to test myself (I detest doing this in my brain).

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 is to say LoyaltyUserDetailsPIIUser property is owned by PIIUser and required.LoyaltyUserDetail property is not required.

You might begin at the opposite end:

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

now reads PIIUser'sLoyaltyUserDetail Optional property and LoyaltyUser'sPIIUser Property is necessary.

You must always employ the HAS/WITH pattern.

You are not alone, and just so you know, one-to-one (or one-to-zero/one) connections are some of the most difficult to configure in code.

96
8/17/2016 3:19:02 AM

Popular Answer

Just act as though you were in a one-to-many relationshipLoyaltyUserDetail and PIIUser hence, your mapping should

modelBuilder.Entity<LoyaltyUserDetail>()
       .HasRequired(m => m.PIIUser )
       .WithMany()
       .HasForeignKey(c => c.LoyaltyUserDetailId);

The only foreign key you should need is not concerned with WithMany, which EF should construct!



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow