2013-09-22 6 views
11

Jak mam odwzorować następującą relację w Entity Framework 5?Entity Framework 5 Code First Self-Referencing Relationship

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; } 
} 

Próbowałem to:

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

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

a to:

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

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

oba wynik w ten błąd:

typów wszystkich właściwości w zależnych Rola ograniczenia referencyjnego musi być taka sama, jak odpowiednie typy właściwości w Pri ncipal Role.

Jeśli zacznę z mapowaniem bazy pierwszego, oto co wygenerowany podmiot wygląda następująco:

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; } 
} 

wiem, że to będzie działać, jeśli zacznę db-pierwszy, po prostu trzeba wiedzieć jak zdefiniuj relację w kodzie-pierwszym.

+0

jest 'Id' własność klucz? A może masz mapowanie klawiszy (z Fluent API?) Na inną właściwość, na przykład na "Wartość"? – Slauma

+0

Id jest podstawową właściwością klucza elementu. – user326502

+0

"* typy wszystkich właściwości w roli zależnej *" oznaczają typy właściwości FK, która jest "ParentItemId" i ma typ 'int?'. "* odpowiednie typy właściwości w głównej roli *" oznaczają typy właściwości PK, która jest "Id" i ma typ 'int'. Są takie same (nieważne nie ma znaczenia). Jednak wyjątek mówi, że tak nie jest. Wyjątek wystąpiłby, gdybyś miał na przykład 'long' (lub dowolny inny typ) dla PK i' int? 'Dla FK. Raczej dziwne ... – Slauma

Odpowiedz

2

Wyjątkiem oznacza następujące:

  • typy wszystkich właściwości w Dependent Role” są rodzaje nieruchomości FK która ParentItemId i ma wpisać int? w modelu
  • "Odpowiednie typy właściwości w głównej roli "są typami właściwości PK, która jest Id i ma typ int w twoim modelu

Są takie same (nieważne nie ma znaczenia). Jednak wyjątek mówi, że tak nie jest.

Wyjątek normalnie występowałby tylko wtedy, gdy typy nie pasują, na przykład, jeśli miałeś long (lub inny typ) dla PK i int? dla FK.

0

Spróbuj użyć metody mapKey zamiast korzystać z HasForeignKey. Jak

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

Dzięki za poświęcenie czasu na odpowiedź. Próbując w ten sposób, otrzymuję następujący błąd: Każda nazwa właściwości w typie musi być unikalna. Nazwa właściwości "ParentItemId" została już zdefiniowana. – user326502

+0

Dodaj ignorowanie do właściwości ParentItemId tuż przed powyższym wiele do jednego mapowania. modelBuilder.Entity () .Ignore (it => it.ParentItemId); –

7

W kodzie najpierw zmienić swoją klasę encji tak:

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; } 
    } 

Wpisz następujący kod do pliku kontekstowego:

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

że to powinno działać.

+0

Dzięki za poświęcenie czasu na odpowiedź. Podczas próby w ten sposób, nadal otrzymuję ten sam błąd: Typy wszystkich właściwości w roli zależnej ograniczenia referencyjnego muszą być takie same, jak odpowiednie typy właściwości w roli głównej. – user326502

3

Dlaczego nie spróbować tego:

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; } 
    } 

A w swojej klasie DataContex:

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

nadzieję, że ta praca.

Również nie jest dobry artykuł tutaj: Jak skonfigurować Samodzielny Odwoływanie podmiotem w kod najpierw http://blogs.microsoft.co.il/gilf/2011/06/03/how-to-configure-a-self-referencing-entity-in-code-first/