Entity Framework Порядок «многие ко многим» - PullRequest
0 голосов
/ 24 октября 2018

У меня есть 3 таблицы: Users, Roles и промежуточная таблица UsersRoles.Как я могу заказать пользователей в соответствии с их именами ролей?

public List<USERS> Find(UserFilter filter, string sortExpression, int maxRows, int startIndex)
{
            var query = db.USERS.Include("ROLES").AsQueryable();

            query = ApplyFilter(query, filter);
            query = query.OrderBy(sortExpression);
            query = ApplyPaging(query, maxRows, startIndex);

            var result = query.ToList();
            return result;
}

private IQueryable<USERS> ApplyOrder(IQueryable<USERS> query, UserFilter filter)
{
        // what should I do here to sort/group according to role name ?
}

private IQueryable<USERS> ApplyFilter(IQueryable<USERS> query, UserFilter filter)
{
        if (!string.IsNullOrEmpty(filter.UserName))
                    query = query.Where(u => u.USERNAME == filter.UserName);
}

private IQueryable<USERS> ApplyPaging(IQueryable<USERS> query, int maxRows, int startIndex)
{
            var result = query;
            if (maxRows != 0)
                result = query.Skip(startIndex).Take(maxRows);
            return result;
}

Я вызываю метод Find с контроллера и использую AsQueryable, так как я могу сгруппировать пользователей по их ролям (ролямдолжны быть отсортированы по названию роли)?что я должен написать в методе ApplyOrder?

1 Ответ

0 голосов
/ 24 октября 2018

Рассмотрим следующий пример:

var users = new user[]
{
     new user()
     {
         Name = "Jan",
         Roles = new Role[]
         {
             new Role() {Name = "Supervisor},
             new Role() {Name = "Teacher"},
         }
     },
     new user()
     {
         Name = "Pierre",
         Roles = new Role[]
         {
             new Role() {Name = "Student"},
             new Role() {Name = "Scholar"},
         }
     }
}

как я могу заказать пользователей в соответствии с их именами ролей?

Что вы имеете в виду?Вы хотите пользователей с ролями, где роли упорядочены по имени?Или вы хотите, чтобы роли упорядочивались по имени вместе с их пользователями?

В любом случае, если вы следовали первым соглашениям кода платформы сущностей, ваши классы для многих для многих будут похожи на следующие:

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

    // every User has zero or more Roles (many-to-many)
    public virtual ICollection<Role> Roles {get; set;}
}
class Role
{
    public int Id {get; set;}
    public string Name {get; set;}

    // every Role has zero or more Users (many-to-many)
    public virtual ICollection<User> Users {get; set;}
}
class MyDbcontext : DbContext
{
    public DbSet<User> Users {get; set;}
    public DbSet<Role> Roles {get; set;}
}

В структуре сущностей столбцы таблиц представлены не виртуальными свойствами.Виртуальные свойства представляют отношения между таблицами.

Этого достаточно для того, чтобы структура сущностей обнаружила, что вы намеревались установить отношение "многие ко многим".Entity Framework создаст для вас соединительную таблицу и будет использовать эту таблицу при необходимости.

Возможно, вам потребуются другие имена для таблиц и столбцов, в этом случае вам понадобится свободный API или атрибуты.Однако классы будут похожи.

Получить пользователей с их ролями, упорядоченными по имени

var result = dbContext.Users
    .Where(user => ...)                    // only if you don't want all Users
    .Select(user => new
    {
         // select only the properties that you plan to use
         Id = user.Id,
         Name = user.Name,

         Roles = user.Roles
             .Where(role => ...)           // only if you don't want all Roles
             .OrderBy(role => role.Name)
             .Select(role => new
             {   // again: select only the properties you plan to use
                 Id = role.Id,
                 Name = role.Name,
             })
             .ToList(),
    });

Одна из более медленных частей запроса - это транспортировка выбранногоданные для вашего локального процесса.Следовательно, не стоит выбирать больше данных, чем вы планируете использовать.Если вы используете include для извлечения данных, вы выбираете все свойства класса, включая внешние ключи.

Например, если вы берете Учителя с Id 4 со всеми его учениками, вы знаете, что каждый из его 1000 Students будет иметь внешний ключ TeacherId со значением 4. Какая трата длятранспортируйте все эти внешние ключи!

Совет: при запросе данных используйте Select, чтобы выбрать свойства, которые вы фактически планируете использовать.Используйте Include только если вы планируете изменить включенный объект

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