Объект со списком одного и того же объекта

#c# #entity-framework #entity-framework-core

#c# #сущность-фреймворк #сущность-фреймворк-ядро

Вопрос:

Я использую ядро EF и пытаюсь создать отношение профиля «следовать» в своем объекте, но при попытке создать миграцию я получаю сообщение об ошибке:

Объект профиля:

 public class Profile {

    [Key]
    public Guid Id { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Profile> FollowersProfiles { get; set; }

    public virtual ICollection<Profile> MembersProfiles { get; set; }

}
  

Поэтому, когда Profile1 я начну следовать Profile2 , у меня будет доступ к этому отношению в FollowingProfiles , а когда Profile1 присоединюсь к Profile2 членству, у меня будет это отношение в MembersProfiles

При запуске dotnet ef migrations add InitialDb я получаю следующую ошибку:

Не удалось определить связь, представленную профилем свойства навигации.FollowersProfiles’ типа ‘ICollection’. Либо настройте связь вручную, либо игнорируйте это свойство, используя атрибут ‘[NotMapped]’ или используя EntityTypeBuilder.Игнорировать’в ‘OnModelCreating’.

Если я удалю одно из ICollection свойств, оно будет работать хорошо.

Ответ №1:

Как указано в вашей ошибке, вам необходимо вручную настроить это отношение.

Сначала вам нужно добавить два дополнительных поля к вашей сущности:

 public class Profile {
    ...
    public virtual Profile ParentProfile { get; set; } //to support ef-core navigation
    public int ParentProfileId { get; set; } //to be used as foreign key
    ...
}
  

Затем вам нужно создать класс, подобный этому:

 public class ProfileConfiguration : IEntityTypeConfiguration<Profile>
{
    public void Configure(EntityTypeBuilder<Profile> builder)
    {
        builder
            .HasOne(x => x.ParentProfile)
            .WithMany(x => x.FollowersProfiles)
            .HasForeignKey(x => x.ParentProfileId)
            .OnDelete(DeleteBehavior.Cascade); // keep an eye on this, Choose the behavior you want
        builder
            .HasOne(x => x.ParentProfile)
            .WithMany(x => x.MembersProfiles)
            .HasForeignKey(x => x.ParentProfileId)
            .OnDelete(DeleteBehavior.Cascade);
    }
}
  

И затем вам нужно использовать эту конфигурацию в вашем контексте, добавив это

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


        // ps: If you already have an override for this method just add the following line to it
        modelBuilder.ApplyConfiguration(new ProfileConfiguration());
    }
  

Комментарии:

1. Не удается создать связь между ‘Profile. MembersProfiles’ и ‘Profile. ParentProfile’, потому что уже существует связь между ‘Profile. FollowersProfiles’ и ‘Profile. ParentProfile’. Свойства навигации могут участвовать только в одном отношении.