[英]EF Core Unique Constraint across multiple tables
如何創建/設計關系和唯一約束:
一個項目有許多SUBJOBS。 SUBJOB有許多任務。 任務具有一個編號,該編號在單個項目中必須唯一。
我為關系嘗試了以下方法,但是我不知道如何對Task.Number
和Project.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
都有一個Project
, Task.ProjectId
應該等於Task.SubJob.ProjectId
(后者從SubJob.Project.ProjectId
獲取值)。 為了確保傳遞此值,我們可以定義Task
和SubJob
之間的關系以使用復合鍵,如下所示
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 });
});
然后,我們可以使用HasAlternateKey
在Number
& ProjectId
定義唯一約束。
您也可以使用帶有ProjectId
復合鍵,但是這可能需要為PK的其他部分設置值生成。
除非您確實需要唯一約束,否則請考慮使用唯一索引。 更多信息可以在這里找到
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.