2013-05-10 84 views
5

我與外鍵有一對一的關係,但由於某種原因,Cascade Delete未啓用。示例代碼如下。代碼第一個一對一啓用級聯刪除

public class AppRegistration 
{ 
    public int AppRegistrationId { get; set; } 
    [Required] 
    [StringLength(50)] 
    [Display(Name = "Username")] 
    public string UserName { get; set; } 
    [Required] 
    [StringLength(100)] 
    public string Password { get; set; } 
    [StringLength(20)] 
    public string StudentOrAgent { get; set; } 
    // navigation properties 
    public virtual AppStatus AppStatus { get; set; } 
    public virtual Agreement Agreement { get; set; } 
    public virtual AnotherTable AnotherTable { get; set; } 
} 

具有外鍵的從屬表如下。

public class Agreement 
{ 
    [Key] 
    [ForeignKey("AppRegistration")] 
    public int AppRegistrationId { get; set; } 
    public DateTime DateAgreed { get; set; } 
    public virtual AppRegistration AppRegistration { get; set; } 
} 

當我嘗試刪除生成的AppRegistrations表中的條目,我得到一個參考約束衝突。

我試着把[Required]放在依賴表中的導航屬性上,但它什麼也沒做--命令顯示了No pending code-based migrations.消息。有任何想法嗎?謝謝。

更新: 我收到以下錯誤信息:

The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.AppStatus_dbo.AppRegistrations_AppRegistrationId". The conflict occurred in database "MVCapp", table "dbo.AppStatus", column 'AppRegistrationId'.

回答

8

我決定在單獨的示例項目中計算出cascade delete問題。我發現以下博客& MSDN頁面非常有用。

使用Code First方法創建以下模型。

public class Category 
{ 
    public int CategoryId { get; set; } 
    public string CategoryName { get; set; } 
    public virtual Book Book { get; set; } 
} 
public class Book 
{ 
    public int CategoryId { get; set; } 
    public string BookTitle { get; set; } 
    public string BookAuthor { get; set; } 
    public string BookISBN { get; set; } 
    public virtual Category Category { get; set; } 
} 

(我知道該實體名稱所暗示的一個一對多的關係,但我想模型1對1的關係,在我原來的問題排在首位。)

所以,在上面的模型中,每個類別只能有一個

在您的DbContext派生類中添加以下內容。

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

    modelBuilder.Entity<Book>() 
     .HasKey(t => t.CategoryId); 

    modelBuilder.Entity<Category>() 
     .HasRequired(t => t.Book) 
     .WithRequiredPrincipal(t => t.Category) 
     .WillCascadeOnDelete(true); 
} 

(以下命名空間所需要的上面的代碼:System.Data.EntitySystem.Data.Entity.ModelConfiguration.Conventions。)

這正確創建1對1的關係。每個表中都有一個主鍵,Book表中的外鍵也啓用ON DELETE CASCADE

Database Diagram for the model

在上面的代碼,在Category實體我用WithRequiredPrincipal()t => t.Category參數,其中所述參數是在從屬表的外鍵列。

如果使用WithRequiredPrincipal()沒有參數,你會得到在Book表一個額外的列,你會在Category表必須在Book表指示兩個外鍵來CategoryId

我希望這個信息有幫助。

UPDATE

後來我找到答案直接在這裏:

http://msdn.microsoft.com/en-us/data/jj591620#RequiredToRequired

5

一個原因,你沒有得到級聯刪除是因爲你的關係是可選的。

如果你想即一個AppRegistration所需的關係必須有一個Agreement你可以使用(級聯刪除自動配置):

public class Agreement 
{ 
    ... 
    [Required] 
    public AppRegistration AppRegistration{ get; set; } 
} 

如果你想要的關係是可選的級聯刪除您可以配置此使用Fluent API:

modelBuilder.Entity<AppRegistration>() 
    .HasOptional(a => a.Agreement) 
    .WithOptionalDependent() 
    .WillCascadeOnDelete(true); 
+0

感謝您的回答。我試着把'[Required]',但代碼遷移的'更新數據庫'返回'沒有待定的基於代碼的遷移。任何方式來解決這個問題? – erdinger 2013-05-10 16:29:19

+1

我可能是錯的,但我認爲你不想嘗試第一種技術,因爲幾乎不可能滿足雙向所需的一對一關係。如果你嘗試插入協議,你會得到違反約束的原因,因爲AppRegistration不存在,反之亦然。 – AaronLS 2013-05-10 16:29:21

+0

@ user2291748您是否在運行update-database之前添加了遷移? AaronLS,嗯,也許你是對的,這只是想到的東西。 – MattSull 2013-05-10 16:34:06