2012-03-28 83 views
0

我有以下兩個實體:EF 4.1層疊在實體之間的兩個方向上兩個關係

public class Tournament { 
    public int TournamentID { get; set; } 
    public String Name { get; set; } 
    public int? OfficialID { get; set; } 

    public virtual Official HeadOfficial { get; set; } 

    public virtual ICollection<Official> Officials { get; set; } 
} 

public class Official { 
    public int OfficialID { get; set; } 
    public String Surname { get; set; } 
    public String FirstName { get; set; } 
    public int TournamentID { get; set; } 

    public virtual Tournament Tournament { get; set; } 
} 

一個比賽可以有0..N官員和官員必須有一個比賽鏈接到它。第二種關係是比賽可能有一個主場。

爲了使EF製作數據庫,我有以下時,正確理解這一點:

protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
     modelBuilder.Entity<Tournament>() 
      .HasOptional(t => t.HeadOfficial) 
      .WithMany() 
      .HasForeignKey(t => t.OfficialID); 

     modelBuilder.Entity<Tournament>() 
      .HasMany(t => t.Officials) 
      .WithRequired(o => o.Tournament) 
      .HasForeignKey(o => o.TournamentID);   
    } 

如果我現在刪除一個比賽,有聯繫的那場比賽的所有官員都將被刪除,這是我想。但是,當我刪除在其中一場比賽中成爲正式官員的官員時,刪除不會引用刪除語句與Tournaments.OfficialID中的參考約束衝突。

回答

1

如果我現在刪除一個錦標賽,所有與 聯繫的官員都將被刪除,這正是我想要的。然而,當我刪除在 錦標賽之一中擔任首席官員的官員時,刪除並未通過引用刪除 聲明與 Tournaments.OfficialID中的參考約束衝突。

我認爲這些是完全不同的情況。第一種情況是因爲數據庫中存在級聯刪除設置(EF在數據庫中創建此規則,因爲這種關係是必需的,這是默認行爲)。

您的第二種關係是可選的,所以默認情況下沒有級聯刪除。更重要的是:我不認爲你想要級聯刪除,因爲這意味着刪除一名官員也會刪除這個官員作爲頭像的比賽。

我只能想象如果官員被刪除,你想設置HeadOfficial參考null。但是沒有自動的方式(比如級聯刪除)。您必須編寫這樣的行爲,例如:

using (var ctx = new MyContext()) 
{ 
    var officialToDelete = ctx.Officials.Single(o => o.OfficialID == 5); 
    var tournaments = ctx.Tournaments.Where(t => t.OfficialID == 5).ToList(); 

    foreach (var tournament in tournaments) 
     tournament.OfficialID = null; 

    ctx.Officials.Remove(officialToDelete); 

    ctx.SaveChanges(); 
} 

我相信foreach循環是沒有必要的,因爲EF將修正內容的關係(=設定的外鍵null)當你調用Remove。 (基本上EF本身在內部執行此循環。)但是,將錦標賽加載到上下文中很重要,因爲EF關心這種關係修正(僅適用於附加(=加載的)實體),而不是數據庫(與級聯刪除)。

+0

你說得對。當我試圖在SMSS中刪除它時,EF當然無法爲我解決這個問題。一旦我在代碼中進行測試,它就不需要添加foreach循環。非常感謝。 – Mekswoll 2012-03-29 00:47:31

+0

@pEkvo:順便說一句:如果它沒有foreach循環,那麼你可以扔掉'tournaments'變量並稍微簡化代碼:'ctx.Tournaments.Where(t => t.OfficialID == 5).Load )'。它只是將對象加載到上下文中,而不將對象返回給列表變量。 – Slauma 2012-03-29 14:02:17

相關問題