簡體   English   中英

跨多個表的EF核心唯一約束

[英]EF Core Unique Constraint across multiple tables

如何創建/設計關系和唯一約束:

一個項目有許多SUBJOBS。 SUBJOB有許多任務。 任務具有一個編號,該編號在單個項目中必須唯一。

我為關系嘗試了以下方法,但是我不知道如何對Task.NumberProject.ProjectId實施唯一約束:

public class ProjectContext : DbContext
{
    public DbSet<Project> Project { get; private set; }

    public DbSet<SubJob> SubJob { get; private set; }

    public DbSet<Task> Task { get; private set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Project>(b =>
        {
            b.HasKey(p => p.ProjectId);
            b.HasAlternateKey(p => p.Code);
        });

        modelBuilder.Entity<SubJob>(b =>
        {
            b.HasKey(s => s.SubJobId);
            b.HasOne(s => s.Project).WithMany(p => p.SubJobs).HasForeignKey(s => s.ProjectId);
            b.HasAlternateKey(s => new { s.ProjectId, s.Code });
        });

        modelBuilder.Entity<Task>(b =>
        {
            b.HasKey(l => l.TaskId);
            b.HasOne(l => l.SubJob).WithMany(s => s.Tasks).HasForeignKey(l => l.SubJobId);
        });
    }
}

public class Project
{
    public int ProjectId { get; private set; }

    public string Code { get; set; }

    public ICollection<SubJob> SubJobs { get; private set; } = new List<SubJob>();
}

public class SubJob
{
    public int SubJobId { get; private set; }

    public int ProjectId { get; private set; }

    public Project Project { get; set; }

    public string Code { get; set; }

    public ICollection<Task> Tasks { get; private set; } = new List<Task>();
}

public class Task
{
    public int TaskId { get; private set; }

    public int SubJobId { get; private set; }

    public SubJob SubJob { get; set; }

    public int Number { get; set; }
}

我看到兩種可能性。 對子類使用自然鍵,因此Subjob可能是{ProjectId,JobCode},而Task可能是{ProjectId,JobCode,Number}。 但是,如果{ProjectId,Number}必須是唯一的,那么它將是PK,而JobCode將是非空FK,但不是PK的一部分。

或者,如果數據庫支持索引視圖,則可以在{ProjectId,Number}上創建具有唯一索引的視圖。

要在Tasks表上定義唯一約束,您需要在Task類中獲取ProjectId值。 修改后的Task實體看起來像這樣。

public class Task
{
    public int TaskId { get; private set; }
    public int SubJobId { get; private set; }
    public SubJob SubJob { get; set; }
    public int Number { get; set; }
    public int ProjectId { get; set; } // Added property
}

由於每個Task都有一個SubJob ,每個SubJob都有一個ProjectTask.ProjectId應該等於Task.SubJob.ProjectId (后者從SubJob.Project.ProjectId獲取值)。 為了確保傳遞此值,我們可以定義TaskSubJob之間的關系以使用復合鍵,如下所示

modelBuilder.Entity<Task>(b =>
{
    b.HasKey(l => l.TaskId);
    b.HasOne(l => l.SubJob).WithMany(s => s.Tasks).HasForeignKey(l => new { l.SubJobId, l.ProjectId })
        .HasPrincipalKey(l => new { l.SubJobId, l.ProjectId });
    b.HasAlternateKey(t => new { t.Number, t.ProjectId });
});

然后,我們可以使用HasAlternateKeyNumberProjectId定義唯一約束。

您也可以使用帶有ProjectId復合鍵,但是這可能需要為PK的其他部分設置值生成。

除非您確實需要唯一約束,否則請考慮使用唯一索引。 更多信息可以在這里找到

暫無
暫無

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

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