One-to-one relationship in EF Core (The child/dependent side could not be determined for the one-to-one relationship)

10,010

Problem is in your Block and JobBlock configuration. According to your requirement these two configurations should be as follows:

public class BlockConfiguration : IEntityTypeConfiguration<Block>
{
    public void Configure(EntityTypeBuilder<Block> builder)
    {
        builder.HasKey(p => p.Id);
        builder.Property(p => p.Id).IsRequired().ValueGeneratedNever();

        builder.HasOne(e => e.JobBlock)
            .WithOne(e => e.Block)
            .HasForeignKey<JobBlock>(p => p.IdBlock); // <--- Here it is
    }
}
public class JobBlockConfiguration : IEntityTypeConfiguration<JobBlock>
{
    public void Configure(EntityTypeBuilder<JobBlock> builder)
    {
        builder.HasKey(p => new { p.IdJob, p.IdBlock });

        // Key property is always required. You don't need to specify it explicitly.

        // You don't need to need specify one-one-one configuration
        //  between `Job and Block` and between `Block and JobBlock` in
        //  two places. You need to specify
        //  it only one place. That's why I have removed these from here.
    }
}
Share:
10,010
wegelagerer
Author by

wegelagerer

Updated on June 26, 2022

Comments

  • wegelagerer
    wegelagerer almost 2 years

    I've been getting the following error message and I can't seem to grasp the reason why have I been getting it. Interestingly when adding migrations I didn't get any errors, but whenever I want to use the context I do get it.

    The child/dependent side could not be determined for the one-to-one relationship between 'Block.JobBlock' and 'JobBlock.Block'. To identify the child/dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship configure them without specifying the inverse.

    A Job can have multiple JobBlocks (one-to-many); single Block can have only one JobBlock (one-to-one). So basically, a JobBlock is a reference table/entity used to reference Job and its Blocks. It is important to mention that a primary key in the JobBlock entity consists of two keys thus making it a compound primary key.

    One might argue that a Block entity should already contain an IdJob property and that the JobBlock entity could be entirely dismissed, but there is some reasoning why it shouldn't be done this way so let's leave it as it is :)

    Models:

    public class Job : IEntity
    {
        public Job()
        {
            JobBlocks = new HashSet<JobBlock>();
        }
    
        public Guid Id { get; set; } = Guid.NewGuid();
        public ICollection<JobBlock> JobBlocks { get; set; }
    }
    
    public class Block : IEntity
    {
        public Guid Id { get; set; } = Guid.NewGuid();
        public JobBlock JobBlock { get; set; }
    }
    
    
    public class JobBlock : IEntity
    {
        public Guid IdJob { get; set; }
        public Job Job { get; set; }
    
        public Guid IdBlock { get; set; }
        public Block Block { get; set; }
    }
    

    EF Configurations:

    public class JobConfiguration : IEntityTypeConfiguration<Job>
    {
        public void Configure(EntityTypeBuilder<Job> builder)
        {
            builder.HasKey(p => p.Id);
            builder.Property(p => p.Id) .IsRequired() .ValueGeneratedNever();
    
            builder.HasMany(e => e.JobBlocks)
                .WithOne(e => e.Job)
                .HasForeignKey(p => p.IdJob);
        }
    }
    
    public class BlockConfiguration : IEntityTypeConfiguration<Block>
    {
        public void Configure(EntityTypeBuilder<Block> builder)
        {
            builder.HasKey(p => p.Id);
            builder.Property(p => p.Id).IsRequired().ValueGeneratedNever();
    
            builder.HasOne(e => e.JobBlock)
                .WithOne(e => e.Block)
                .HasForeignKey<JobBlock>(p => new { p.IdJob, p.IdBlock });
        }
    }
    
    public class JobBlockConfiguration : IEntityTypeConfiguration<JobBlock>
    {
        public void Configure(EntityTypeBuilder<JobBlock> builder)
        {
            builder.HasKey(p => new { p.IdJob, p.IdBlock });
            builder.Property(p => p.IdJob).IsRequired();
            builder.Property(p => p.IdBlock).IsRequired();
    
            builder.HasOne(e => e.Job)
                .WithMany(e => e.JobBlocks)
                .HasForeignKey(p => p.IdJob);
    
            builder.HasOne(e => e.Block)
                .WithOne(e => e.JobBlock)
                .HasForeignKey<JobBlock>(p => new { p.IdJob, p.IdBlock });
        }
    }
    
  • Ivan Stoev
    Ivan Stoev about 5 years
    Good, but you don't need to / should not configure any (not only one-to-one) relationship in two places, so remove the other relationship configuration from JobBlockConfiguration as well.
  • TanvirArjel
    TanvirArjel about 5 years
    @IvanStoev Yes! You are correct! I did not notice this. Thanks a lot.
  • wegelagerer
    wegelagerer about 5 years
    @TanvirArjel Unfortunately I still get the same result even though the configurations look exactly as in your answer. Error message is still the same.
  • TanvirArjel
    TanvirArjel about 5 years
    @wegelagerer I have tested in my side with a test project and everything generated perfectly without any issue. Please check your code again. And please also add the IEntity base to the question.
  • wegelagerer
    wegelagerer about 5 years
    @TanvirArjel IEntity is empty, it isn't relevant for this case. Strange, because the code is 1:1 copy of your, but still doesn't work. Thank you anyway, I'll look into it.
  • TanvirArjel
    TanvirArjel about 5 years
    @wegelagerer Better directly copy my code and replace your Block and JobBlock configuration. I assume you did not make changes for Block block configuration as I have done.
  • wegelagerer
    wegelagerer about 5 years
    @TanvirArjel - Ok, it's a bit embarassing to admit, but I've been using the wrong DbContext (I have 2 which are almost the same) :) I'll accept your answer since you gave me valuable infos on how to improve the configurations