2012-12-04 61 views
54

我想禁用級聯刪除鏈接表與實體框架代碼優先。例如,如果許多用戶有很多角色,並且我嘗試刪除某個角色,則我希望該刪除被阻止,除非當前沒有與該角色關聯的用戶。我已經刪除了級聯我OnModelCreating刪除約定:如何在EF代碼優先中禁用級聯刪除鏈接表?

protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
    ... 
    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 

然後,我設置的用戶角色鏈接表:

modelBuilder.Entity<User>() 
    .HasMany(usr => usr.Roles) 
    .WithMany(role => role.Users) 
    .Map(m => { 
     m.ToTable("UsersRoles"); 
     m.MapLeftKey("UserId"); 
     m.MapRightKey("RoleId"); 
    }); 

然而,當EF創建數據庫,它創造了一個刪除級聯外鍵關係,例如。

ALTER TABLE [dbo].[UsersRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.UsersRoles_dbo.User_UserId] FOREIGN KEY([UserId]) 
REFERENCES [dbo].[User] ([UserId]) 
ON DELETE CASCADE 
GO 

ALTER TABLE [dbo].[UsersRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.UsersRoles_dbo.Role_RoleId] FOREIGN KEY([RoleId]) 
REFERENCES [dbo].[Role] ([RoleId]) 
ON DELETE CASCADE 
GO 

如何阻止EF生成此刪除級聯?

回答

93

我得到了答案。 :-)由於ManyToManyCascadeDeleteConvention,這些級聯刪除正在創建。您需要刪除這個約定,以防止它從創建級聯刪除鏈路表:

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 
+0

謝謝,這幫了我一噸。好奇的是,你最終刪除了兩個約定還是隻是多對多的約定? – kmehta

+7

其實,我剛剛結束了刪除一對多的約定,並選擇性地重新啓用一個或兩個實體。我的筆記說,因爲(與一對多不同)你不能使用Fluent API通過使用'.WillCascadeOnDelete(true)',* all *來重新啓用多對多級聯刪除。多對多表必須級聯或不級聯。我認爲讓他們所有的級聯成爲這些惡意中較小的一個,因爲大多數情況下,如果我使用多對多鏈接表刪除鏈接的內容,我希望它所鏈接的內容也被刪除。 – Jez

+1

這似乎不起作用。我的問題是當我有一個相同類型的對象的兩個屬性(由該用戶創建,並由該用戶最後編輯)。我希望這會刪除「可能導致循環或多個級聯路徑」錯誤,但我得到,但它沒有工作。建議? – Rogala

0

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

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

AddForeignKey("dbo.UsersRoles", "UserId", "dbo.User", "UserId", cascadeDelete: false);

0

我同意Ebram哈利勒是將其關閉單個表是一個很好的選擇。我喜歡但是堅持儘可能靠近自動生成遷移,因爲我可以,所以我把它架在OnModelCreating:

modelBuilder.Entity<User>() 
    .HasMany(usr => usr.Roles) 
    .WithMany(role => role.Users) 
    .Map(m => { 
     m.ToTable("UsersRoles"); 
     m.MapLeftKey("UserId"); 
     m.MapRightKey("RoleId"); 
    }) 
    .WillCascadeOnDelete(false); 

我相信這將保留刪除去另一個方向,因此,如果既需要阻塞(在這個例子中是有道理的)類似的呼叫將需要以Entity<User>(Role)

開始作出。當然,這個問題在問題被問到後會過時。所以它可能不會在2012年有效。