Как мне создать отношения между пользователем и подписчиками с помощью Code 1st Entity framework

#c# #entity-framework #asp.net-core

#c# #entity-framework #asp.net-core

Вопрос:

Как мне создать отношения «многие» между пользователем и подписчиками с помощью Code 1st Entity framework. Я попытался использовать следующий код

   public class User : IdentityUser<int>
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public List<User> Followers { get; set; }
      
    }
 

но, похоже, это не работает

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

1. В каком смысле это не работает? Как вы можете сказать? Если есть ошибки, пожалуйста, поделитесь ими.

Ответ №1:

Чтобы создать отношения, ссылающиеся на себя, вам нужно будет явно настроить отношения. Для начала вам нужно будет назначить FK с нулевым значением, чтобы подписчик мог вернуться к основному пользователю. Объявление этого как свойства FK было бы чем-то вроде:

 public class User : IdentityUser<int>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    
    public int? FollowingUserId { get; set; }
    public virtual User FollowingUser { get; set; }
    public virtual ICollection<User> Followers { get; set; }      
}
 

Оттуда вам нужно будет настроить сопоставление. Используя ModelBuilder, это было бы что-то вроде:

 modelBuilder.Entity<User>()
    .HasOptional(x => x.FollowingUser)
    .WithMany(x => x.Followers)
    .HasForeignKey(x => x.FollowingUserId);
 

Вы можете использовать свойство Shadow для FK:

 public class User : IdentityUser<int>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    
    public virtual User FollowingUser { get; set; }
    public virtual ICollection<User> Followers { get; set; }      
}

modelBuilder.Entity<User>()
    .HasOptional(x => x.FollowingUser)
    .WithMany(x => x.Followers)
    .HasForeignKey("FollowingUserId");
 

Который сообщает EF использовать столбец FollowingUserId в таблице без двух источников истинности для отношения в сущности. (пользователь.FollowingUserId против user.FollowingUserId.Идентификатор пользователя)

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

 public class User : IdentityUser<int>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    
    public virtual User FollowingUser { get; set; }
}

modelBuilder.Entity<User>()
    .HasOptional(x => x.FollowingUser)
    .WithMany()
    .HasForeignKey("FollowingUserId");
 

Вы все равно можете получить список подписчиков для конкретного пользователя:

 var followers = context.Users.Where(x => x.FollowingUser.UserId == userId);
 

Хотя это может усложнить некоторые типы запросов, например, если вы хотите перечислить всех пользователей с указанием количества их подписчиков. (Требуется GroupBy без навигационной ссылки для EF для обработки запроса)

Одним из дополнительных моментов, которые я бы рекомендовал, было бы сохранить IdentityUser отдельно от «User» или такого, который отображается и связан друг с другом. В IdentityUser будут содержаться сведения, касающиеся аутентификации и авторизации, которые вы не захотите раскрывать или потенциально изменять при обновлении сведений о пользователях и их отношениях друг с другом. Например, если у нас есть «Blogger» и «User», где User равен аутентификации, а Blogger представляет пользователей системы в области отношений и общих сведений о персонаже, Blogger может содержать идентификатор пользователя (или у пользователя может быть BloggerId) без навигационной ссылки, чтобы избежать случайной утечки информации об аутентификации, если вынапример, мы должны были сериализовать сущности.