簡體   English   中英

如何在有周期和多個級聯路徑的地方配置級聯刪除

[英]How to configure cascade delete where there are cycles and multiple cascade paths

我很難理解這種關系,以及如何為它設置級聯刪除設置。

  • 有一張員工表,其中每個員工都有任意數量的手柄,附件和作業
  • 有一張表的句柄,其中每個句柄都屬於一個雇員,可以在工具中使用
  • 有一個附件表,其中每個附件都屬於一個雇員,可以在工具中使用
  • 有一張工具表,其中每個工具由一個附件,一個手柄組成,可用於任何數量的作業
  • 有一張工作表,其中每個工作都屬於一個員工,並且可能使用或可能不使用工具

注意:句柄和附件可能存在而沒有用於制作工具

簡而言之:員工可以混合使用手柄和附件來制作工具,然后在分配給他們的工作中使用工具。

該圖顯示了數據庫是如何連接在一起的(可以隨時提出更好的設計建議

數據庫圖

這就是模型的設置方式,“作業”模型對工具FK(ToolId)具有可為空的引用,因此無需工具即可存在作業。

public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; }

    public List<Handle> Handles { get; set; }
    public List<Attachment> Attachments { get; set; }
    public List<Job> Jobs { get; set; }
}
public class Handle
{
    public int HandleId { get; set; }
    public string Material { get; set; }
    public double ExpectedLife { get; set; }
    public double LifetimeMaintenance { get; set; }

    public int EmployeeId { get; set; }
    public Employee Employee { get; set; }
    public List<Tool> Tools { get; set; }
}
public class Attachment
{
    public int AttachmentId { get; set; }
    public string Material { get; set; }
    public string Type { get; set; }
    public double ExpectedLife { get; set; }
    public double LifetimeMaintenance { get; set; }

    public int EmployeeId { get; set; }
    public Employee Employee { get; set; }
    public List<Tool> Tools { get; set; }
}
public class Tool
{
    public int ToolId { get; set; }
    public string OperationSpeed { get; set; }


    public int HandleId { get; set; }
    public Handle Handle { get; set; }

    public int AttachmentId { get; set; }
    public Attachment Attachment { get; set; }

    public List<Job> Jobs { get; set; }
}
public class Job
{
    public int JobId { get; set; }
    public string Name { get; set; }
    public double EffortRequired { get; set; }

    public int EmployeeID { get; set; }
    public Employee Employee { get; set; }
    public int? ToolId { get; set; }
    public Tool Tool { get; set; }
}

這就是創建數據庫上下文的方式。 有一個級聯刪除設置,用於在刪除工具時將“作業”中的工具FK(ToolId)設置為null(因此,刪除其工具時不會刪除該作業)。

public class ToolsDbContext : DbContext
{
    public ToolsDbContext(DbContextOptions<ToolsDbContext> options) : base(options)
    {

    }

    public DbSet<Employee> employees { get; set; }
    public DbSet<Handle> handles { get; set; }
    public DbSet<Attachment> attachments { get; set; }
    public DbSet<Tool> tools { get; set; }
    public DbSet<Job> jobs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Tool>()
            .HasMany(j => j.Jobs)
            .WithOne(t => t.Tool)
            .OnDelete(DeleteBehavior.SetNull);
    }
}

創建遷移是可行的,但是隨后更新數據庫失敗,並顯示以下錯誤:

Introducing FOREIGN KEY constraint 'FK_tools_handles_HandleId' on table 'tools' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.

我不太確定如何理解此錯誤。

通過以下方式進行思考:

  • 如果刪除了句柄,它將刪除它使用的所有工具,從而將相關Jobs中的ToolId設置為null
  • 如果附件被刪除,它將刪除其使用的所有工具,從而將相關Jobs中的ToolId設置為null
  • 如果刪除工具,則會將相關作業中的ToolId設置為null
  • 如果刪除作業,則不會產生級聯效果

因此,我認為問題一定出在刪除雇員上,但是我不明白為什么(還?)...

  • 如果刪除員工,則應刪除所有內容; 它應該刪除所有相關的作業,句柄和附件。 然后,那些刪除的句柄或附件應依次刪除與它們相關聯的工具(無關緊要的是什么)。

因此,有一些級聯路徑刪除了一個雇員,但是我希望這一切都將根據模型設置保持原樣。 如果是這樣,我不確定應該如何配置...

注意:如果數據庫中沒有員工模型,一切似乎都可以正常工作

SQL Server不允許在數據庫中具有指向同一表的多個級聯路徑。 在您的情況下,其中有兩個工具:

  • 員工->處理->工具
  • 員工->附件->工具

解決此問題的所有方法都包括為一個關系或另一個關系設置DeleteBehavior.Restrict,例如:

  • 為實體設置DeleteBehavior.Restrict->處理關系並通過觸發器處理此級聯路徑(否則“ restrict”將不允許刪除對其引用的記錄)
  • 為實體設置DeleteBehavior.Restrict->處理關系並在應用程序代碼中處理此級聯路徑(在刪除主要實體之前,顯式更新/刪除所有相關實體)
  • 為兩個實體關系設置“限制”行為

等等...

你說:

有一張員工表,其中每個員工都有任意數量的手柄,附件和作業

但是您的圖在一個員工和一個手柄之間建立了直接鏈接,一個手柄有很多員工,而一個員工只有一個手柄

您的陳述與圖表沖突

從數據庫的角度來看,我認為這種建模是錯誤的。 我認為工作應該有雇員。 (如果一個工作有多個雇員,則需要另一個表雇員將一個工作ID映射到多個雇員。)一個工作有一個工具,一個工具有一個手柄和一個附件。 我看不到為什么刪除雇員應該刪除他們的工作(如果我解雇了某人,但他為我工作時蓋的房子仍然存在),但是您可以在不使用級聯約束的情況下進行清理

最終,您可以在圖中看到已創建的循環。 如果刪除1端的內容會刪除*端的所有內容,則刪除圖表中的任何內容都會啟動一條鏈,該鏈采用一條分離的路徑,該路徑會重新組合在一起。 刪除員工實體確實可以解決這個問題

最終,員工不應直接擁有工作,把手或附件

暫無
暫無

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

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