Запрос ролей удостоверения EF Core - PullRequest
1 голос
/ 10 июля 2020

Я использую. NET Core 3.1, и я хочу запросить пользователей в моей базе данных.

Итак, я изменил свой класс ApplicationUser следующим образом:

public class ApplicationUser : IdentityUser
{
    public ICollection<IdentityUserRole<string>> UserRoles { get; set; }
}

И теперь я пытаюсь запросить пользователей.

var users = from u in DbContext.Users
            select new UserViewModel
            {
                Email = u.Email,
                EmailConfirmed = u.EmailConfirmed,
                Phone = u.PhoneNumber,
                Roles = u.UserRoles.Select(r => r.Role.Name) // Whoops! Won't work
            };

Проблема в том, что UserRoles имеет свойство RoleId, но у них нет свойства Role.

Итак, как мне получить имена этих ролей?

Обновление:

Основываясь на комментариях Джавада, я изменил свой код следующим образом:

public class ApplicationUser : IdentityUser
{
    public ICollection<IdentityRole> Roles { get; set; }
}

И

Users = (from u in DbContext.Users
         select new UserViewModel
         {
             Email = u.Email,
             EmailConfirmed = u.EmailConfirmed,
             Phone = u.PhoneNumber,
             Roles = u.Roles.Select(r => r.Name)
         })
         .ToList();

Я думал, что не могу этого сделать, потому что это отношения «многие ко многим». Но на самом деле он компилируется. Однако, когда я запускаю его, я получаю сообщение об ошибке.

Недопустимое имя столбца ApplicationUserId.

Я не уверен, где указывается это имя столбца. Похоже, что это не имя столбца в базе данных.

Обновление 2:

Оказывается, указанная выше ошибка связана с ожиданием миграции базы данных. Однако я не хотел менять базу данных. Как я изначально подозревал, я не могу выполнить ApplicationUser.ICollection<IdentityRole>, потому что есть промежуточная таблица.

Итак, я запустил его, но он не дал результатов (потому что нет внешних ключей от IdentityRole до ApplicationUser.

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

Ответы [ 2 ]

1 голос
/ 10 июля 2020

Итак, я не знаю, почему IdentityUserRole не включает свойство IdentityRole. Это кажется ненужным ограничением.

В конце концов, я просто изменил свой запрос.

var users = await (from u in DbContext.Users
                   join ur in DbContext.UserRoles on u.Id equals ur.UserId
                   join r in DbContext.Roles on ur.RoleId equals r.Id
                   select new
                   {
                       u.Email,
                       u.EmailConfirmed,
                       u.PhoneNumber,
                       Role = r.Name
                   })
                   .ToListAsync();

Users = (from u in users
         group u.Role by u into g
         select new UserViewModel
         {
             Email = g.Key.Email,
             EmailConfirmed = g.Key.EmailConfirmed,
             Phone = g.Key.PhoneNumber,
             Roles = string.Join(", ", g)
         })
         .ToList();

Мне не удалось заставить group by работать в запросе, поэтому я ' m сгруппируйте его после получения данных.

В любом случае, это работает.

1 голос
/ 10 июля 2020

Вы должны создать новый класс с названием что-то вроде ApplicationUserRole, который наследуется от IdentityUserRole<string>, тогда вам просто нужно определить отношения между ApplicationUser -> ApplicationUserRole и ApplicationRole -> ApplicationUserRole.

modelBuilder.Entity<ApplicationUserRole>(entity =>
{
    entity
      .HasOne(x => x.Role)
      .WithMany(x => x.UserRoles)
      .HasForeignKey(x => x.RoleId);

    entity
      .HasOne(x => x.User)
      .WithMany(x => x.UserRoles)
      .HasForeignKey(x => x.UserId);
 });

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

public class ApplicationUserRole : IdentityUserRole<string>
{
    public ApplicationUser User { get; set; }

    public ApplicationRole Role { get; set; }
}

public class ApplicationUser : IdentityUser<string>
{
    public ICollection<ApplicationUserRole> UserRoles { get; set; }
}

public class ApplicationRole : IdentityRole<string>
{
    public ICollection<ApplicationUserRole> UserRoles { get; set; }
}
...