2013-09-22 83 views
11

如何在實體框架5中映射以下關係?實體框架5代碼優先自引用關係

public class Item { 
    public int Id { get; set; } 
    public int? ParentItemId { get; set; } 
    public string Value { get; set; } 

    public Item ParentItem { get; set; } 
    public List<Item> ChildItems { get; set; } 
} 

我已經試過這樣:

protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
    base.OnModelCreating(modelBuilder); 

    modelBuilder.Entity<Item>() 
       .HasOptional(i => i.ParentItem) 
       .WithMany(i => i.ChildItems) 
       .HasForeignKey(i => i.ParentItemId); 
} 

這:

protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
    base.OnModelCreating(modelBuilder); 

    modelBuilder.Entity<Item>() 
       .HasMany(i => i.ChildItems) 
       .WithOptional(i => i.ParentItem) 
       .HasForeignKey(i => i.ParentItemId); 
} 

即:在這個錯誤的結果:

在從屬類型的所有屬性參照約束的作用必須與Pri中相應的屬性類型相同首席角色。

如果我開始使用數據庫第一映射,這裏是生成的實體是什麼樣子:

public partial class Item 
{ 
    public Item() 
    { 
     this.ChildItems = new HashSet<Item>(); 
    } 

    public int Id { get; set; } 
    public Nullable<int> ParentItemId { get; set; } 
    public string Value { get; set; } 

    public virtual ICollection<Item> ChildItems { get; set; } 
    public virtual Item ParentItem { get; set; } 
} 

我知道如果我開始與這個將工作DB-第一,我只需要知道如何在代碼優先中定義關係。

+0

是'Id'關鍵特性?或者你有一個鍵映射(與Fluent API?)到另一個屬性,例如「Value」? – Slauma

+0

Id是Item的主鍵屬性。 – user326502

+0

「* Dependent Role *中所有屬性的類型」是指'ParentItemId'並且類型爲'int?'的FK屬性的類型。 「*主體角色*中的相應屬性類型」表示屬性爲「Id」且類型爲「int」的PK屬性的類型。它們是相同的(可空性無關緊要)。但是,例外說,他們不是。如果你有例如PK的long(或其他類型)和FK的'int?',就會發生異常。相當奇怪...... – Slauma

回答

2

唯一的例外是指如下:

  • 類型的從屬角色所有屬性的」是類型FK屬性,它是ParentItemId,並在模型中鍵入int?
  • 「主體角色中的相應屬性類型」是PK屬性的類型,其爲Id並且在您的模型中具有類型int

它們是相同的(可空性無關緊要)。但是,例外說,他們不是。

例外通常只會發生,如果類型不匹配,例如如果您有一個long(或任何其他類型)的PK和一個int?爲FK。

0

嘗試使用mapKey而不是使用HasForeignKey。像

modelBuilder.Entity<Course>() 
    .HasRequired(c => c.Department) 
    .WithMany(t => t.Courses) 
    .Map(m => m.MapKey("ChangedDepartmentID")); 
+0

感謝您花時間回答。以這種方式嘗試時,出現以下錯誤:類型中的每個屬性名稱都必須是唯一的。屬性名稱'ParentItemId'已經被定義。 – user326502

+0

前右上述許多添加忽略到ParentItemId屬性一對一映射.. modelBuilder.Entity ()結尾。可以忽略(它=> it.ParentItemId); –

7

在代碼首先改變你的實體類像這樣:

public class Item 
    { 
     public Item() 
     { 
      this.ChildItems = new HashSet<Item>(); 
     } 

     public int Id { get; set; } 
     public Nullable<int> ParentItemId { get; set; } 
     public string Value { get; set; } 

     public virtual Item ParentItem { get; set; } 
     public virtual ICollection<Item> ChildItems { get; set; } 
    } 

寫下面的代碼到你的環境文件:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Item>() 
        .HasOptional(i => i.ParentItem) 
        .WithMany(i => i.ChildItems) 
        .HasForeignKey(i => i.ParentItemId); 
    } 

認爲這應該工作。

+0

感謝您抽出寶貴時間來回答。當嘗試這種方式,我仍然得到了同樣的錯誤: 類型的引用約束的從屬角色所有屬性必須是相同的主體作用相應的屬性類型。 – user326502

3

爲什麼不試試這個:

public class Item 
    { 
     public Item() 
     { 
      ChildItems = new HashSet<Item>(); 
     } 

     public int Id { get; set; } 
     public int? ParentItemId { get; set; } 
     public string Value { get; set; } 

     public virtual Item ParentItem { get; set; } 
     public virtual ICollection<Item> ChildItems { get; set; } 
    } 

而在你DataContex類:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Item>() 
        .HasOptional(i => i.ParentItem) 
        .WithMany() 
        .HasForeignKey(i => i.ParentItemId); 
    } 

希望這項工作。

也有一個很好的文章在這裏: 如何在代碼中首先配置的自參考實體 http://blogs.microsoft.co.il/gilf/2011/06/03/how-to-configure-a-self-referencing-entity-in-code-first/