簡體   English   中英

Entity Framework Core - 將兩個連接映射到同一個表

[英]Entity Framework Core - mapping two joins to the same table

我有兩個表 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
}

在此表中,我使用以下方法引用客戶端表:

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”和“Job.WarrantyCompany”之間創建關系,因為“Client.Jobs”和“Job.Client”之間已經存在關系。 導航屬性只能參與單個關系。

這是不言而喻的。 我還嘗試從工作表的角度創建關系:

modelBuilder.Entity<Job>()
    .HasOne(a => a.Client)
    .WithOne(b => b.WarrantyCompany)
    .HasForeignKey<Client>(b => b.WarrantyCompanyId);

我發現當有兩個返回到同一個客戶端表時,我無法將關系可視化。

從本質上講,簡而言之,我有一個客戶可以有一個到多個工作,但對於每個工作,我可能有一個可選的保修公司,其中保修公司是客戶。 客戶和工作之間的兩種關系。

如何在這兩個表之間具有主要關系和次要可選關系,以及二級保修公司關系是一對一還是一對多?

出現此問題是由於兩個關系被映射到 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);

為了便於閱讀,我簡化了表格屬性。

客戶表:

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

它將生成一個表和這樣的關系。

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM