2013-05-27 163 views
0

我有兩個類:實體框架許多一對多關係錯誤

public class Cluster 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Blob> Blobs { get; set; } 
} 

public class Blob 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Cluster> Clusters { get; set; } 
} 

public ClusterConfiguration() 
{ 
    this.HasKey(p => p.Id) 
     .HasRequired(p => p.Frame) 
     .WithMany(p => p.Clusters) 
     .HasForeignKey(p => p.FrameId) 
     .WillCascadeOnDelete(true) 
     ; 

    this.HasMany(p => p.Blobs) 
     .WithMany(p => p.Clusters) 
     ; 
} 

public BlobConfiguration() 
{ 
    this.HasKey(p => p.Id) 
     .HasRequired(p => p.Frame) 
     .WithMany(p => p.Blobs) 
     .HasForeignKey(p => p.FrameId) 
     .WillCascadeOnDelete(true) 
     ; 

    this.HasMany(p => p.Clusters) 
     .WithMany(p => p.Blobs) 
     ; 
} 

有在這些類其他表的引用,但我不認爲這是問題。錯誤是:

[{"Introducing FOREIGN KEY constraint 'FK_dbo.ClusterBlobs_dbo.Blob_Blob_Id' on table 'ClusterBlobs' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.\r\nCould not create constraint. See previous errors."}].

我不太知道如何告訴EF級聯刪除斑點,如果集羣被刪除,但如果斑點被刪除不刪除集羣。請指教。

更新:順便說一下使用EF5。

回答

1

的多個級聯刪除路徑實際上是在效果,如果你刪除一個Frame,而不是一個ClusterBlob

  • Frame被刪除 - >瀑布到Clusters - >級聯鏈接表
  • Frame是刪除 - >瀑布到Blobs - >級聯鏈接表

所以,這些都是從Frame兩個路徑鏈接表。

我建議禁用從FrameClusterBlob的兩個(或兩個)關係之一的級聯刪除。 (在那裏使用WillCascadeOnDelete(false)。)禁用鏈接表的級聯刪除不可能基於個人關係。唯一的辦法是禁用全局的約定:

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 

但是,這將影響到模型中的所有許多一對多的關係。

我不太確定如果刪除羣集 但如果刪除Blob時不刪除羣集,如何告知EF級聯刪除Blob。

這是順便說不可能的。這裏是因爲從數據庫角度來看,許多一對多的關係,實際上是有兩個與之間的聯繫表一個一對多的關係模型ClusterBlob之間沒有級聯刪除。級聯刪除僅作用於關係中依賴關係的鏈接表上。 ClusterBlob都是委託人。

+0

謝謝@Slauma。我爲自己編寫了一個ORM方法,並假定報告EF級別的錯誤而不是傳遞從數據庫生成的底層約束錯誤會很容易。'[爲鏈接表禁用級聯刪除是不可能的]。我假設這是一個數據庫級限制,而不是EF。另外,我應該想到級聯刪除不適用於規範化的多對多關係。只是到目前爲止,我的模型中這兩個對象的身份還沒有很好地定義。 –

+0

順便說一句,因爲級聯刪除僅適用於一個路徑,所以爲其他路徑寫入一些手動刪除代碼最合適的地方是什麼? –

+0

@RaheelKhan:是的,這是一個數據庫級(SQL Server)限制。對於其他數據庫,它可能毫無例外地工作。我相信EF不知道刪除路徑。最合適的地方將取決於你的架構。如果您有(非通用)存儲庫可能在'Frame'的Delete方法中。 – Slauma

0

我相信,在全球關閉ManyToManyCascadeDeleteConvention是不是一個明智的選擇。相反,最好只關閉表,關閉

這可以通過編輯生成的遷移文件來實現,屬性爲cascadeDelete。例如:

AddForeignKey("dbo.ClusterBlobs", "Blob_Id", "dbo.Blob", "Blob_Id", cascadeDelete: false);