EF Core один-ко-многим или многие-ко-многим? пользователи <-> друзья - PullRequest
0 голосов
/ 11 ноября 2018

Я собираюсь реализовать модуль user-friends в моем проекте.

Допустим, у меня есть 2 простых класса:

public class User
{
    int Id { get; set; }
    string Name { get; set; }
}

и класс FriendShip (который является отношением междуuser)

   public class FriendShip
   {
       int User1Id { get; set; }
       int User2Id { get; set; }
       int Status  { get; set; }
   }

Статус Enum

Логика для этих 2 классов:

  • , когда первый пользователь приглашает второго пользователя в свой список дружбы,в базе данных должно быть создано 2 объекта

    user1Id: 1,
    user2Id: 2,
    Status: 1, (where 1 means 'invited')
    

    и

    user1Id: 2,
    user2Id: 1,
    Status: 0,    (where 0 means 'nonaccepted')
    
  • , когда второй пользователь примет это, эти 2 состояния будут обновлены значением 3 (гдеозначает «дружба» или что-то в этом роде - но забудьте о логике сейчас.

Я не знаю, как я могу создать эту структуру базы данных из кода (в C #)

это будет один-ко-многим, как один пользователь может иметь много отношений с другими пользователями?

у вас должен быть закрытый ключ 2 fk: user1, user2

проблема в том, чтоэти 2 внешних ключа идут в одну таблицу (Пользователи)

Я пытался что-то вроде этого:

    modelBuilder.Entity<User>()
        .HasMany(x=>x.UsersFriendships)
        .WithOne(x=>x.User2)

    modelBuilder.Entity<UsersFriendship>()
        .HasMany(x=> x.Users)
        .WithOne(x=>x.UsersFriendships)

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

.WithOne(x => x.userFriendships)

Самый простой способ - набрать в построителе модели:

 modelBuilder.Entity<UsersFriendship>()
        .HasKey(x => new { x.User1Id, x.User2Id });

и класс UserFriendship будет выглядеть так:

   public class UsersFriendship
    {

        [ForeignKey("User1Id")]
        public User User1 { get; set; }

        [ForeignKey("User2Id")]
        public User User2 { get; set; }

        public int User1Id { get; set; }
        public int User2Id { get; set; }
        public RelationStatus RelationStatus { get; set; }
    }

но теперь я не могу переходить от сущности пользователя к его друзьям (например, User.Friendship)

и когда я добавляю свойство навигации в класс пользователя:

public virtual List<UsersFriendship> UsersFriendships { get; set; }

в базе данных будет четыре поля: user1Id, user2Id, status, userId

последнее поле получено из пользовательского класса (поле UsersFriendships) <- и мне не нужно это поле в моей базе данных! </p>

1 Ответ

0 голосов
/ 11 ноября 2018

Вы можете найти один пример в официальных документах: https://docs.microsoft.com/en-us/ef/core/modeling/relationships#many-to-many.

Я настроил этот пример, чтобы отразить ваш случай:

namespace foo
{
  public class User
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual List<UsersFriendship> UsersFriendships { get; set; }
  }

  public class Friendship
  {
      public User User1 { get; set; }
      public int User1Id { get; set; }
      public User User2 { get; set; }
      public int User2Id { get; set; }
      public int Status  { get; set; }
  }

  class MyContext : DbContext
  {
      public DbSet<Friendship> Friendships { get; set; }
      public DbSet<User> Users { get; set; }

      protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
          modelBuilder.Entity<Friendship>()
              .HasKey(fs => new { fs.User1, fs.User2, fs.Status });

          modelBuilder.Entity<Friendship>()
              .HasOne(fs => fs.User1)
              .WithMany(u => u.UsersFriendships)
              .HasForeignKey(fs => fs.User1);

          modelBuilder.Entity<Friendship>()
              .HasOne(fs => fs.User2)
              .WithMany(u => u.UsersFriendships)
              .HasForeignKey(fs => fs.User2);
      }
  }

последнее поле получено из класса пользователя (поле UsersFriendships) <- и я не хочу, чтобы это поле было в моей базе данных! </p>

При регистрации этого свойства навигации (см. Мой код) оно не будет сохранено в БД.

В других случаях, если по какой-то причине вы не хотите, чтобы свойство сохранялось в db ядром ef, пометьте свойство атрибутом [NotMapped] (namespace System.ComponentModel.DataAnnotations.Schema).

...