EF Core中的一对一关系(一对一关系无法确定child/dependent端)
One-to-one relationship in EF Core (The child/dependent side could not be determined for the one-to-one relationship)
我一直收到以下错误消息,但我似乎无法理解为什么会收到它。有趣的是,在添加迁移时我没有遇到任何错误,但每当我想使用上下文时我都会得到它。
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.
一个Job
可以有多个JobBlocks
(一对多);单个 Block
只能有一个 JobBlock
(一对一)。所以基本上,JobBlock
是一个引用 table/entity,用于引用 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 });
}
}
问题出在您的 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.
}
}
我一直收到以下错误消息,但我似乎无法理解为什么会收到它。有趣的是,在添加迁移时我没有遇到任何错误,但每当我想使用上下文时我都会得到它。
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.
一个Job
可以有多个JobBlocks
(一对多);单个 Block
只能有一个 JobBlock
(一对一)。所以基本上,JobBlock
是一个引用 table/entity,用于引用 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 });
}
}
问题出在您的 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.
}
}