Запрос к пользователям отношений «многие ко многим» -> Классы

#c# #postgresql #.net-core #many-to-many #backend

#c# #postgresql #.net-ядро #многие ко многим #серверная часть

Вопрос:

У меня есть две сущности, пользователи и классы, с отношением «многие ко многим». Я работаю с .Net Core, и я установил отношения, следуя этому сообщению в блоге ЗДЕСЬ (вплоть до части 3). База данных работает, и я могу добавлять классы и заполнять таблицу соединений, но я не знаю, как получить все классы, в которых зарегистрирован пользователь, или наоборот, всех пользователей, которые зарегистрированы в определенном классе.

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

User.cs

 public class User : IdentityUser
{
    // Making the classes a JoinCollectionFacade allows us to perform actions like adding a class
    public User()
        => Classes = new JoinCollectionFacade<Class, UserClass>(
            UserClass,
            uc => uc.Class,
            c => new UserClass { User = this, Class = c });

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Type { get; set; }
    //public string Email { get; set; }
    public string Phone { get; set; }
    public string Membership { get; set; }

    private ICollection<UserClass> UserClass { get; } = new List<UserClass>();

    // This element does not need to be mapped. It's used for easier reference
    // to the Users enrolled in the class
    [NotMapped]
    public ICollection<Class> Classes { get; }
}
  

Class.cs

 public class Class
{

    // Making the classes a JoinCollectionFacade allows us to perform actions like adding a class
    public Class()
        => Users = new JoinCollectionFacade<User, UserClass>(
            UserClass,
            uc => uc.User,
            u => new Models.UserClass { User = u, Class = this });

    public Class(Instructor i, string d)
    {
        Instructor = i;
        Description = d;
    }

    public int Id { get; set; }
    public virtual Instructor Instructor { get; set; } // Made virtual so we can take advantage of certain Entity Framework such as lazy loading (from Microsoft docs)
    public string Description { get; set; }
    public DateTime StartTime { get; set; }
    public DateTime EndTime { get; set; }

    private ICollection<UserClass> UserClass { get; } = new List<UserClass>();

    // This element does not need to be mapped. It's used for easier reference
    // to the Users enrolled in the class
    [NotMapped]
    public ICollection<User> Users { get; }
}
  

UserClass.cs

 public class UserClass
{
    public string UserId { get; set; }
    public User User { get; set; }

    public int ClassId { get; set; }
    public Class Class { get; set; }
}
  

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

1. По крайней мере, вы должны опубликовать эти 2 класса. Класс User должен иметь коллекцию объектов класса, поэтому, если вы запрашиваете конкретного пользователя и включаете список классов, вы получаете то, что вам нужно. Я могу только предположить, что объекты отображаются подобным образом на основе вашего описания.

2. Я отредактировал вопрос и включил свои классы.

3. Попробуйте удалить эти NotMapped атрибуты, и вы сможете включить их в свой запрос.

4. Для меня это не решает проблему. Не могли бы вы привести мне пример запроса, который я ищу?

5. Ваша проблема в том, что вы следовали подходу какого-то блога, который не позволяет вам выполнять includes, что в точности является решением вашей проблемы. Вы можете увидеть наглядный пример здесь внизу.

Ответ №1:

Я решил свою проблему с помощью

  • создание общедоступных экземпляров UserClass как в User.cs, так и в Class.cs
  • используя этот вид запроса ниже, чтобы получить всех пользователей, зарегистрированных в определенном классе
 var usersInClass = _context.Users
                      .Include(i => i.UserClass).ThenInclude(i => i.Class)
                      .Where(x => x.UserClass.Select(pc => pc.Class).Any(c => c.Id == id))
                      .ToList();