EF Core 中的一对一关系(无法确定一对一关系的子/依赖方)

Posted

技术标签:

【中文标题】EF Core 中的一对一关系(无法确定一对一关系的子/依赖方)【英文标题】:One-to-one relationship in EF Core (The child/dependent side could not be determined for the one-to-one relationship) 【发布时间】:2019-08-22 13:51:08 【问题描述】:

我收到了以下错误消息,但我似乎无法理解为什么会收到它。有趣的是,在添加迁移时我没有收到任何错误,但每当我想使用上下文时,我都会得到它。

无法确定一对一的孩子/依赖方 “Block.JobBlock”和“JobBlock.Block”之间的关系。到 识别关系的子/依赖方,配置 外键属性。如果这些导航不应该是 相同的关系配置它们而不指定逆。

一个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】:

问题在于您的 BlockJobBlock 配置。根据您的要求,这两种配置应如下:

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.
    

【讨论】:

好,但是你不需要/不应该在两个地方配置any(不仅仅是一对一)关系,所以也从JobBlockConfiguration 中删除其他关系配置。 @IvanStoev 是的!你是对的!我没有注意到这一点。非常感谢。 @TanvirArjel 不幸的是,即使配置看起来与您的答案完全相同,我仍然得到相同的结果。错误信息还是一样。 @wegelagerer 我已经在我身边用一个测试项目进行了测试,一切都完美地生成了,没有任何问题。请再次检查您的代码。并请在问题中添加IEntity 基数。 @TanvirArjel - 好吧,承认有点尴尬,但我一直在使用错误的 DbContext(我有 2 个几乎相同):) 我会接受你的回答,因为你给了我有关如何改进配置的宝贵信息

以上是关于EF Core 中的一对一关系(无法确定一对一关系的子/依赖方)的主要内容,如果未能解决你的问题,请参考以下文章

具有一对一关系的 EF Core 批量插入

EF Core中通过Fluent API配置一对一关系

EF Core 一对一关系交换引用问题

EF Core 一对一 一对多 多对多 关系定义

EF Core中通过Fluent API配置一对一关系

EF Core中通过Fluent API配置一对一关系