Отношение один-к-одному в EF Core (дочерняя / зависимая сторона не может быть определена для отношения один-к-одному) - PullRequest
1 голос
/ 01 апреля 2019

Я получаю следующее сообщение об ошибке, и я не могу понять причину, почему я его получаю.Интересно, что при добавлении миграций я не получаю никаких ошибок, но всякий раз, когда я хочу использовать контекст, я получаю его.

Дочерняя / зависимая сторона не может быть определена для непосредственного отношенияотношения между 'Block.JobBlock' и 'JobBlock.Block'.Чтобы определить дочернюю / зависимую сторону отношения, настройте свойство внешнего ключа.Если эти переходы не должны быть частью одного и того же отношения, настройте их без указания обратного.

A Job может иметь несколько JobBlocks (один ко многим);один Block может иметь только один JobBlock (один к одному).Таким образом, по сути, JobBlock является справочной таблицей / сущностью, используемой для ссылки на Job и ее Blocks.Важно отметить, что первичный ключ в сущности JobBlock состоит из двух ключей, что делает его составным первичным ключом.

Можно утверждать, что сущность Block уже должна содержать свойство IdJobи что сущность JobBlock может быть полностью отклонена, но есть некоторые причины, почему это не следует делать таким образом, поэтому давайте оставим все как есть :)

Модели:

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 Конфигурации:

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 });
    }
}

1 Ответ

2 голосов
/ 01 апреля 2019

Проблема в вашей конфигурации Block и JobBlock.Согласно вашему требованию эти две конфигурации должны быть следующими:

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.
    }
}
...