2012-08-02 84 views
4

我有一個Page類,它與類似的頁面相關聯。每個關聯都有關於關聯的其他信息。這是已被定義爲Page的表示的類。實體框架代碼與同類的第一個雙重關係

public class Page { 
    [Key] 
    public virtual int Id { get; protected set; } 
    [Required] 
    [StringLength(32)] 
    public virtual string Name { get; set; } 
    [InverseProperty("Page")] 
    public virtual ICollection<Association> Associations { get; set; } 
} 

每個頁面都可以與任意數量的其他頁面關聯。這被定義爲源和目標頁面。我不介意這種關聯是單向還是雙向的,在我的特定情況下(我更喜歡雙向關聯,很難)是合理的。這是關聯類..

public class Association { 
    [Key, Column(Order = 0)] 
    public virtual int PageId { get; protected set; } // SOURCE 
    [Required] 
    public virtual Page Page { get; set; } // SOURCE 
    [Key, Column(Order = 1)] 
    public virtual int TargetId { get; protected set; } // TARGET 
    [Required] 
    public virtual Page Target { get; set; } // TARGET 
    [Required] 
    [StringLength(32)] 
    public virtual string InformationAboutTheAssociation { get; set; } 
} 

現在我有以下的背景下...

public class DbCtx : DbContext { 
    public DbSet<Association> Associations { get; set; } 
    public DbSet<Page> Pages { get; set; } 
} 

而問題是,SQL Express的抱怨可能的循環引用(這是不是這樣,但它是過度保護)。如何解決生成的方案以接受所描述的方案?

Introducing FOREIGN KEY constraint 'FK_dbo.Associations_dbo.Pages_TargetId' on table 'Associations' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. 

謝謝!

+0

哪個EF? 4.3,5.0? – 2012-08-02 21:21:13

+0

要麼。我現在使用5.0,但也可以使用4.3。 – 2012-08-02 21:42:22

+0

使用5.0。它在速度部門有所改進。 – amb 2012-08-02 22:01:42

回答

4

響應

做什麼錯誤告訴你。 指定ON DELETE NO ACTION或ON UPDATE NO ACTION。既然你有兩個外鍵給同一個實體,並且默認on delete cascade爲默認的on delete cascade,所以你必須先禁用這個外鍵,因爲當一個頁面被刪除時,這個關聯會試圖被第一個外鍵刪除,但會失敗,因爲的第二個外鍵。

修改3

public class DbCtx : DbContext { 
public DbSet<Association> Associations { get; set; } 
public DbSet<Page> Pages { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
     modelBuilder.Entity<Association>() 
      .HasRequired(x => x.Page) 
      .WithMany(x => x.Associations) 
      .WillCascadeOnDelete(false); 
    } 

}

我認爲這應該工作。

刪除頁面實體

因爲你沒有on delete cascade在協會做,如果你試圖刪除頁面,如果你有這取決於你想要刪除的頁面實體協會實體就會失敗。

所以,當你想刪除一個頁面,你必須首先刪除所有的關聯,引用頁面。你有一個外部約束(其中兩個實際上)從Association到Page。只使用其中的一個並保持一致(頁面或目標)。

既然你問了這個問題,我只能斷定你並不知道SQL是如何工作的,所以如果你還讀了一本關於設計數據庫和使用SQL的書,那會更好。


我沒有第一次使用的代碼EF但考慮到實體關係圖,頁面有「1對多」公司章程和協會有兩個「1對1」的頁面。

是不是循環的,因爲它看起來像,它是一個糟糕的設計。

規範化數據庫。

如果您要設計數據庫(首先是數據庫),則不需要頁面和關聯之間的「1對多」關係,因爲您已與關聯「1到1」(其中兩個關係)到頁面。 所以,如果你想尋找一個特定的關聯知道PAGID你可以有一個select * from association where pageId or targetId = the id you are looking for

,如果您第一次使用EF與數據庫,你就必須從頁面關聯一個反向引用(你正在嘗試做的),但不是在數據庫本身的實際實體關係模型。它們是虛擬參考。

編輯:

我重讀的問題,問題是該協會第二參考頁。這很奇怪,因爲數據庫首先在這種情況下正常工作。

我會考慮它。

+1

準確地說,如何在沒有實體引用自身的情況下對樹層次結構的關係模型(或者在這種情況下是有向圖)進行規範化?任何「一對多」關係實際上只是您提出的改變所具有的「一對一」或「多對一」關係的逆轉。使用ORM的主要優點之一是它們可以直觀地導航並在模型類中顯式捕獲,而不必處理「虛擬引用」。 – millimoose 2012-08-02 21:08:54

+0

你必須對樹層次更具體。父實體不需要具有對子實體的引用(只有子實體具有父實體的外鍵)。你可以讓實體引用自己(因爲設計),並不意味着它是循環的,但在這種情況下,循環警告看起來是正確的,因爲你實體之間互相引用。 – amb 2012-08-02 21:15:15

+0

即使我使用ORM(並且我使用它很多),我仍然傾向於手動設計我的數據庫,然後首先使用EF數據庫。來回引用會自動添加,實際上是因爲它們不駐留在數據庫方案中。在引擎蓋下,後退引用僅僅是一個'你不寫的通過主鍵選擇'。 – amb 2012-08-02 21:16:32

相關問題