2012-03-02 48 views
0

我是EF新手,剛開始一個新項目。我目前有一個型號爲BrandManagers的主鍵和三個外鍵。我不明白我應該如何映射這些在DbContext在EF代碼優先的同一對象上映射多個外鍵

public class BrandManager 
{ 
    public int BrandManagerId { get; set; } 

    [Required()] 
    public int PersonId { get; set; } 

    [Required()] 
    public int BrandId { get; set; } 

    [Required()] 
    public int CountryId { get; set; } 

    public virtual Person Person { get; set; } 
    public virtual Brand Brand { get; set; } 
    public virtual Country Country { get; set; } 
} 

我該如何映射這個?我已經嘗試了下面,無濟於事。

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Person>() 
     .HasRequired(x => x.Country); 

    modelBuilder.Entity<Brand>() 
     .HasMany(x => x.BrandManagers); 

    modelBuilder.Entity<BrandManager>() 
     .HasRequired(x => x.Person); 
    modelBuilder.Entity<BrandManager>() 
     .HasRequired(x => x.Brand); 
    modelBuilder.Entity<BrandManager>() 
     .HasRequired(x => x.Country); 

    base.OnModelCreating(modelBuilder); 
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
} 

我不斷收到

表「人」引進國外KEY約束「FK_Person_Country_CountryId」可能會導致循環或多個級聯路徑。

我沒有找到在ASP.NET網站上的介紹教程,這個具體問題的任何解決方案,也沒有在這裏SO關於這方面的任何問題,所以我開始覺得我誤解EF的一些基本部分。

回答

2

我的回答是更具體要怎麼你在EF Code First中映射外鍵。我正準備在第二部分關於多重級聯路徑的工作,當時寬恕的回答是正確的。所以,不要扔掉我的答案,這可能對您有所幫助,下面是一般如何在EF中映射外鍵的答案:)。在底部的級聯刪除上稍微有點兒。

您可以在模型構建器中使用數據註釋而無需映射。但是,如果您不希望您的POCO對象用數據庫註釋標記,我也使用modelBuilder提供瞭解決方案。

另一個需要注意的是,只要你有Person參考,你不需要PersonId。在這種情況下,生成器會爲您創建FK(並且您的POCO類不會擁有它不需要的Id)。不過,將Id用於延遲加載可能是更好的做法(我不確定這是否是您做這件事的原因)。

最後,如果遵循約定,則甚至不需要設置外鍵。因此,如果您的Country類具有Id的PK,那麼當您使用CountryId創建Country參考時,EF將通過CountryId是國家參考的FK的命名來實現。(Source

數據註釋:

public class BrandManager 
{ 
    public int BrandManagerId { get; set; } 

    [Required()] 
    public int PersonId { get; set; } 

    [Required()] 
    public int BrandId { get; set; } 

    [Required()] 
    public int CountryId { get; set; } 

    [ForeignKey("PersonId")] 
    public virtual Person Person { get; set; } 
    [ForeignKey("BrandId")] 
    public virtual Brand Brand { get; set; } 
    [ForeignKey("CountryId")] 
    public virtual Country Country { get; set; } 
} 

的DbContext:(同樣,在這種情況下,你不應該需要在你的POCO類中的任何數據的註解,因爲它們都被設置在模型構建器)

modelBuilder.Entity<BrandManager>() 
    .HasRequired(x => x.Person) 
    .WithMany(x=>x.People) 
    .HasForeignKey(x=>x.PersonId); 

至於具體的錯誤,您需要添加.WillCascadeOnDelete(false),正如寬恕指出的BrandManager-> Country。您可以刪除Person-> Country,但刪除BrandManager會更好,因爲它最終會通過Person路徑級聯。

+0

事情現在有道理。謝謝你的回答。 – sshow 2012-03-05 09:56:37

1

您遇到的問題是SqlServer問題。對於外鍵關係和刪除級聯中的多條刪除路徑,它往往非常保守。

你從品牌經理和個人的關係到國家的關係。一對一國刪除會產生兩個路徑品牌經理:

Country -> Person -> Brand Manager 
Country -> Brand Manager 

的解決方案是,以消除刪除這些實體的一個級聯:

// Remove the cascade for country->Brand Manager. 
// Let it cascade through Person instead 
modelBuilder.Entity<BrandManager>() 
    .HasRequired(x => x.Country) 
    .WillCascadeOnDelete(false);