我有两个表Clients和Jobs。客户可以有许多工作。但是,我在Jobs上有第二种关系,该关系也应回溯到称为WarrantyCompany的客户。基本上,保修公司也是客户。客户/工作关系是主要关系,但是我想第二次返回客户表以获取保修公司的详细信息。
这是“客户”表:
using JobsLedger.DATA.Entities.Interfaces;
using JobsLedger.DATA.Interfaces;
using System;
using System.Collections.Generic;
namespace JobsLedger.DATA.Entities
{
#nullable enable
public class Client : IEntityBase, IAuditedEntityBase
{
public Client()
{
Jobs = new List<Job>();
}
public int Id { get; set; }
// One warranty company client to a job.
public int? WarrantyCompanyId { get; set; }
public Job? WarrantyCompany { get; set; }
// One suburb to a client.
public int? SuburbId { get; set; }
public Suburb? Suburb { get; set; }
// If its a warranty company then we simply link it one to one to the brand id.
public Brand? Brand { get; set; }
public virtual ICollection<Job> Jobs { get; set; } = default!;
public virtual ICollection<Job> WarrantyCompanyJobs { get; set; } = default!;
}
#nullable disable
}
我正在使用以下方式引用作业表:
// One warranty company client to a job.
public int? WarrantyCompanyId { get; set; }
public Job? WarrantyCompany { get; set; }
工作表如下:
using JobsLedger.DATA.Entities.Interfaces;
using JobsLedger.DATA.Interfaces;
using System.Collections.Generic;
namespace JobsLedger.DATA.Entities
{
public class Job : IEntityBase, IAuditedEntityBase
{
#nullable enable
public Job()
{
Visits = new List<Visit>();
}
public int Id { get; set; }
public int? WarrantyCompanyId { get; set; }
public Client? WarrantyCompany { get; set; }
public int ClientId { get; set; } = default!;
public Client Client { get; set; } = default!;
}
#nullable disable
}
在此表中,我使用以下方法引用到client表:
public int? WarrantyCompanyId { get; set; }
public Client? WarrantyCompany { get; set; }
我正在使用Entity Framework Core Fluent API创建关系。
我决定从客户的角度考虑两种关系:
// Two one to many relationships between client and job.
modelBuilder.Entity<Client>()
.HasMany(t => t.Jobs)
.WithOne(g => g.Client)
.HasForeignKey(g => g.ClientId)
.OnDelete(DeleteBehavior.Restrict);
// Same table but a client can also be a warranty agent.
modelBuilder.Entity<Client>()
.HasMany(a => a.Jobs)
.WithOne(b => b.WarrantyCompany)
.HasForeignKey(b => b.WarrantyCompanyId);
我尝试创建迁移,但是出现以下错误:
无法在“ Client.Jobs”和“ Client.Jobs”之间建立关系 'Job.WarrantyCompany',因为两者之间已经存在关系 “ Client.Jobs”和“ Job.Client”。导航属性只能 参加一个单一的关系。
这是不言而喻的。我还尝试从作业表的角度创建关系:
modelBuilder.Entity<Job>()
.HasOne(a => a.Client)
.WithOne(b => b.WarrantyCompany)
.HasForeignKey<Client>(b => b.WarrantyCompanyId);
当有两个返回到同一客户表时,我发现无法可视化这种关系。
简而言之,本质上,我有一个可以从事一对多工作的客户,但是对于这些工作,我可能会设置一个可选的保修公司,其中保修公司是客户。客户与工作之间的两种关系。这两个表之间如何具有主要关系以及次要可选关系,并且次要保修公司关系是一对一还是一对多?
答案 0 :(得分:1)
由于两个关系被映射到Client类中的同一Jobs集合而发生此问题。由于实际上存在两个关系,因此它们不能重用相同的属性。
您的客户模型已经具有第二种关系的集合。您只需要修复映射。
// First client/job relationship
modelBuilder.Entity<Client>()
.HasMany(t => t.Jobs)
.WithOne(g => g.Client)
.HasForeignKey(g => g.ClientId)
.OnDelete(DeleteBehavior.Restrict);
// Second client/job relationship (warranty)
modelBuilder.Entity<Client>()
.HasMany(a => a.WarrantyCompanyJobs)
.WithOne(b => b.WarrantyCompany)
.HasForeignKey(b => b.WarrantyCompanyId);
答案 1 :(得分:1)
为了简化可读性,我简化了表格属性。
客户表:
public class Client
{
public int Id { get; set; }
// One warranty company client to a job.
public int? WarrantyCompanyId { get; set; }
public Job? WarrantyCompany { get; set; }
public ICollection<Job> Jobs { get; set; } = default!;
public ICollection<Job> WarrantyCompanyJobs { get; set; } = default!;
}
和作业表:
public class Job
{
public int Id { get; set; }
public int? WarrantyCompanyId { get; set; }
public Client? WarrantyCompany { get; set; }
public int ClientId { get; set; } = default!;
public Client Client { get; set; } = default!;
}
为了进行配置,我创建了一个JobConfig
类
public class JobConfig : IEntityTypeConfiguration<Job>
{
public void Configure(EntityTypeBuilder<Job> builder)
{
builder.HasOne(s => s.Client)
.WithMany(g => g.Jobs)
.HasForeignKey(f => f.ClientId);
builder.HasOne(s => s.WarrantyCompany)
.WithMany(g => g.WarrantyCompanyJobs)
.HasForeignKey(f => f.WarrantyCompanyId);
}
}
在Context
类中,假设上下文类名称为ProjectContext
,则我重写OnModelCreating
方法。
public class ProjectContext: DbContext
{
public ProjectContext()
{
}
public Client Client { get; set; }
public Job Job { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new JobConfig());
}
}
它将生成一个这样的表和关系。