Search code examples
asp.net-coreentity-framework-coreone-to-one

EF Core. Multiple One-to-One-or-Zero relationships between two entities (tables)


I designed three entities with navigation properties (code first approach, unnecessary properties are omitted):

Image (represents image info in database):

public class Image
{
    public long Id { get; init; }

    public long? PlayerId { get; set; }
    public Player Player { get; set; }

    public long? PublicationId { get; set; }
    public Publication Publication { get; set; }
}

Publication (some domain entity):

public class Publication
{
    public long Id { get; init; }

    public long? ImageTitleId { get; set; }
    public Image ImageTitle { get; set; }

    public long? ImageBackgroundId { get; set; }
    public Image ImageBackground { get; set; }
}

Player (some domain entity):

public class Player
{
    public long Id { get; init; }

    public long? ImageProfileId { get; set; }
    public Image ImageProfile { get; set; }

    public long? ImageLogoId { get; set; }
    public Image ImageLogo { get; set; }
}

Business rules are:

  1. Image is dependent entity in all cases
  2. Publication/Player is principal entity in these relationships
  3. Publication/Player can have related image or not (one-to-one-or-zero)

The difficulty for me here is multiple relationships between two entities (therefore tables in database) (Title Image, Background Image, etc).

EF can not automatically detect principal/dependent entity and i can not figure out how to config Fluent API in such case.


Solution

  • I think you missed some properties in Image Entity. I changed Image model as below:

    public class Image
    {
        public long Id { get; init; }
    
        public long? ImageProfilePlayerId { get; set; }
        public Player ImageProfilePlayer { get; set; }
    
        public long? ImageLogoPlayerId { get; set; }
        public Player ImageLogoPlayer { get; set; }
    
    
        public long? ImageTitlePublicationId { get; set; }
        public Publication ImageTitlePublication { get; set; }
    
        public long? ImageBackgroundId { get; set; }
        public Publication ImageBackground { get; set; }
    }
    

    and Paley and Publication as below (they are same as yours):

     public class Publication
    {
        public long Id { get; init; }
    
        public long? ImageTitleId { get; set; }
        public Image ImageTitle { get; set; }
    
        public long? ImageBackgroundId { get; set; }
        public Image ImageBackground { get; set; }
    }
    
    public class Player
    {
        public long Id { get; init; }
    
        public long? ImageProfileId { get; set; }
        public Image ImageProfile { get; set; }
    
        public long? ImageLogoId { get; set; }
        public Image ImageLogo { get; set; }
    }
    

    and used below config for models in OnModelCreating in DbContext:

       protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Image>(e => {
                e.HasOne(x => x.ImageProfilePlayer).WithOne(x => x.ImageProfile).HasForeignKey<Player>(x => x.ImageProfileId).IsRequired(false);
                e.HasOne(x => x.ImageLogoPlayer).WithOne(x => x.ImageLogo).HasForeignKey<Player>(x => x.ImageLogoId).IsRequired(false);
                e.HasOne(x => x.ImageTitlePublication).WithOne(x => x.ImageTitle).HasForeignKey<Publication>(x => x.ImageTitleId).IsRequired(false);
                e.HasOne(x => x.ImageBackground).WithOne(x => x.ImageBackground).HasForeignKey<Publication>(x => x.ImageBackgroundId).IsRequired(false);
            });
    
         
        }
    

    the result is : enter image description here