2014-01-23 147 views
11

因此,在這裏有幾個類似的問題,但我仍然有問題,以確定我在我的簡化方案中錯過了什麼。實體框架6:代碼第一級聯刪除

比方說,我有以下表,照顧好自己巧妙地命名爲:

'JohnsParentTable' (Id, Description) 
'JohnsChildTable' (Id, JohnsParentTableId, Description) 

利用收集到的類看起來像這樣

public class JohnsParentTable 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
    public virtual ICollection<JohnsChildTable> JohnsChildTable { get; set; } 

    public JohnsParentTable() 
    { 
     JohnsChildTable = new List<JohnsChildTable>(); 
    } 
} 

internal class JohnsParentTableConfiguration : EntityTypeConfiguration<JohnsParentTable> 
{ 
    public JohnsParentTableConfiguration() 
    { 
     ToTable("dbo.JohnsParentTable"); 
     HasKey(x => x.Id); 
     Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     Property(x => x.Description).HasColumnName("Description").IsRequired().HasMaxLength(50); 
    } 
} 

public class JohnsChildTable 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
    public int JohnsParentTableId { get; set; } 
    public JohnsParentTable JohnsParentTable { get; set; } 
} 

internal class JohnsChildTableConfiguration : EntityTypeConfiguration<JohnsChildTable> 
{ 
    public JohnsChildTableConfiguration() 
    { 
     ToTable("dbo.JohnsChildTable"); 
     HasKey(x => x.Id); 
     Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     Property(x => x.Description).HasColumnName("Description").IsRequired().HasMaxLength(50); 
     HasRequired(a => a.JohnsParentTable).WithMany(c => c.JohnsChildTable).HasForeignKey(a => a.JohnsParentTableId); 
    } 
} 

在我父表與行數據庫Id爲1,並且子表中的兩行與此父項綁定。如果我這樣做:

var parent = db.JohnsParentTable.FirstOrDefault(a => a.Id == 1) 

該對象正確填充。但是,如果我嘗試刪除該行:

var parent = new Data.Models.JohnsParentTable() { Id = 1 }; 
db.JohnsParentTable.Attach(parent); 
db.JohnsParentTable.Remove(parent); 

db.SaveChanges(); 

實體框架嘗試執行以下操作:

DELETE [dbo].[JohnsParentTable] 
WHERE ([Id] = @0) 
-- @0: '1' (Type = Int32) 
-- Executing at 1/23/2014 10:34:01 AM -06:00 
-- Failed in 103 ms with error: The DELETE statement conflicted with the REFERENCE constraint "FK_JohnsChildTable_JohnsParentTable". The conflict occurred in database "mydatabase", table "dbo.JohnsChildTable", column 'JohnsParentTableId'. 
The statement has been terminated. 

那麼我的問題是,究竟是什麼我缺少保證實體框架知道它必須刪除刪除父項之前的'JohnsChildTable'行?

回答

11

這取決於你是否希望實體框架刪除的孩子,或者你希望數據庫照顧它。

如果您希望EF爲所有子項生成刪除語句,並在刪除父項之前執行這些刪除語句,則必須先將所有子項加載到內存中。

所以你不能簡單地創建一個只有密鑰填充的「虛擬」實體,並期望孩子被刪除。

爲了這個工作,你必須讓數據庫處理刪除。

但子表上的外鍵必須啓用級聯刪除。如果是這樣,實體框架只是爲父對象創建一條刪除語句,並且數據庫也知道要刪除這些子對象。

如果需要關係,Entity Framework會創建一個默認啓用級聯刪除的外鍵,就像您的情況一樣。 (外鍵不能爲空)。

如果您自己創建了數據庫,則必須記住啓用它。

-1

在Visual Studio中打開模型文件。右鍵單擊父 - 子關係並選擇屬性。

在End1 OnDelete屬性上,該值可能爲None。另一種選擇是Cascade;設置它。現在刪除父母會將刪除級聯給子級。

enter image description here

乾杯 -

+8

的OP問題是代碼第一位。此解決方案僅適用於Model First。 – vidalsasoon

15

我認爲最好重寫OnModelCreating方法並添加此代碼。

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<JohnsChildTable>() 
       .HasRequired(t=>t.JohnsParentTable) 
       .WithMany(t=>t.JohnsChildTables) 
       .HasForeignKey(d=>d.JohnsParentTableId) 
       .WillCascadeOnDelete(true); 

      base.OnModelCreating(modelBuilder); 
} 

我設置爲true WillCascadeOnDelete(真)

+0

只是一個警告:據我所知,上面的代碼**不會**使EF級聯刪除未加載到內存中的孩子。 – Riva