Entity Framework 5 Code First Self-Referencing Relationship

Как мне сопоставить следующие отношения в Entity Framework 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);
}

которые приводят к этой ошибке:

Типы всех свойств зависимой роли ссылочного ограничения должны быть такими же, как соответствующие типы свойств в главной роли.

Если я начинаю с сопоставления с базой данных, вот что созданный объект выглядит следующим образом:

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-first, мне просто нужно знать, как определить отношения в первом коде.

Ответ 1

Исключение означает следующее:

  • "типы всех свойств в зависимой роли" являются типами свойства FK, которое является ParentItemId и имеет тип int? в вашей модели
  • "соответствующие типы свойств в главной роли" являются типами свойств PK, которые являются Id и имеют тип int в вашей модели

Они одинаковы (недействительность не имеет значения). Однако исключение говорит, что это не так.

Исключение обычно возникает только в том случае, если типы не совпадают, например, если у вас есть long (или любой другой тип) для PK и int? для FK.

Ответ 2

В коде сначала измените класс сущности следующим образом:

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

Думайте, что это должно сработать.

Ответ 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/

Ответ 4

Попробуйте использовать метод mapKey, а не использовать HasForeignKey. Как

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