2014-09-22 3 views
2

В моем приложении ASP.NET MVC 5 я хочу перечислить роли пользователя. Я загрузил некоторые образцы, которые, кажется, сломаны. В основном я хочу как идентификатор роли, так и имя роли ролей выбранного пользователя (а не текущего пользователя!).Невозможно создать постоянное значение типа «IdentityUserRole». Поддерживаются только примитивные типы или типы перечислений

ApplicationUser.Roles дает мне объект IdentityUserRole с только RoleId и UserId.

ApplicationDbContext.Roles дает мне IdentityRole с RoleId, RoleName и т. Д. Всех ролей приложений.

Так что я хочу, это набор результатов с пересечением обоих наборов, сохраняя при этом полную информацию о роли, чтобы я мог использовать как ее идентификатор роли, так и имя роли.

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

Я попытался следующим на LINQPad (с соответствующими разными цветами и пространствами имен):

string UserName = "[email protected]"; 
ApplicationDbContext ctx = new ApplicationDbContext(); 
var allroles = ctx.Roles.OrderBy(r => r.Id); 
allroles.Dump(); // dumps well, 6 roles 

ApplicationUser user = ctx.Users.Where(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault(); 
var myroles = user.Roles; 
myroles.Dump();  // dumps well, 3 roles 

IEnumerable<IdentityRole> list = from roles in allroles 
    join uroles in myroles 
    on roles.Id equals uroles.RoleId 
    select roles; 
list.Dump(); // exception 

И хотя запрос, по-видимому, не вызывает ошибки во время выполнения, его демпинг делает независимо от того, использую ли я Dump() или явный foreach (элемент IdentityRole в списке). Ошибка, которую я получаю в этом случае:

«Невозможно восстановить постоянное значение типа «Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole». Только примитивные типы или перечисление в этом контексте поддерживаются типы ".

+0

Вы пробовали делать вместо выбора ролей, выберите новый IdentityRole {Id = роль.Id, Name = role.Name} .ToList(); – grimurd

+0

Не могли бы вы пометить один из ответов так, как это принято, поэтому SO не столкнется с этим вопросом на первой странице? –

ответ

0

Вы можете использовать комбинацию этих двух подходов вы пробовали, где вы получите роли из контекста, которые присутствуют в ApplicationUser «s Roles собственности ...

var roles = ApplicationDbContext.Roles 
           .Where(ar => 
             ApplicationUser.Roles 
                 .Select(ur => 
                   ur.RoleId) 
                 .Contains(ar.RoleId)); 
+0

попробовал его в LinqPad, но так же, как и выше, когда я пытаюсь перечислить значения, я получаю «Невозможно создать постоянное значение типа ...» NotSUpportedException. –

0

Вы можете сделать это так:

var rolesList = allroles.ToList().Join(myroles.ToList(), 
             left => left.Id, 
             right => right.RoleId, 
             (left,right) => left); 

Таким образом, он работает для меня по разному сценарию.

0

Проблема в том, что вы не вызываете метод ToList(), который выполняет запрос немедленно (все будет храниться в памяти).

Для лучшего понимания - метод ToList() преобразует IEnumerable<T> в List<T>.

Таким образом, ваш код будет выглядеть следующим образом:

var allroles = ctx.Roles.OrderBy(r => r.Id).ToList();  
var myroles = user.Roles.ToList(); 
0

Вы пытаетесь присоединиться к в памяти список, myroles, с IQueryable, allroles, который производит новый IQueryable: list. Однако этот новый IQueryable переведен в SQL, поэтому myroles также должен быть переведен на SQL. Это не поддерживается для списков не-примитивных типов.

Решение присоединиться к двум IQueryable S:

var myroles = ctx.Users.Where(u => u.UserName == UserName).SelectMany(u => u.Roles); 

var list = from role in allroles 
      join urole in myroles 
      on role.Id equals urole.RoleId 
      select role; 
Смежные вопросы

 Смежные вопросы