在我的ASP.NET MVC 5应用程序中,我想列出用户的角色。我下载了一些似乎被打破的样本。基本上我想要所选用户的角色的角色ID和角色名称(不是当前用户!)。
ApplicationUser.Roles为我提供了一个只有RoleId和UserId的IdentityUserRole对象。
ApplicationDbContext.Roles为我提供了一个包含所有应用程序角色的RoleId,RoleName等的IdentityRole。
所以我想要的是一个结果集,其中包含两个集合的交集,同时保留完整的角色信息,以便我可以同时使用其角色ID和角色名称。
我尝试过Intersect(),但这并不起作用,因为两个对象都是不同类型的。我尝试了愚蠢的迭代风格,但有一个例外,说DAta Reader已经处于活动状态,所以我很难过:(
我在LinQPad上尝试了以下内容(带有适当的conenctions和名称空间):
string UserName = "user@email.com";
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项),它的转储都会发生。我在这种情况下得到的错误是
&#34;无法创建类型&#39; Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole&#39;的常量值。在此上下文中仅支持原始类型或枚举类型&#34;。
答案 0 :(得分:1)
这里唯一的问题是你没有调用立即执行查询的ToList()
方法(一切都将保存在内存中)。
为了更好地理解,ToList()
方法会将IEnumerable<T>
转换为List<T>
。
因此,您的代码将如下所示:
var allroles = ctx.Roles.OrderBy(r => r.Id).ToList();
var myroles = user.Roles.ToList();
答案 1 :(得分:0)
您可以结合使用您尝试过的两种方法,从ApplicationUser
的{{1}}属性中获取上下文中的角色...
Roles
答案 2 :(得分:0)
你可以这样做:
var rolesList = allroles.ToList().Join(myroles.ToList(),
left => left.Id,
right => right.RoleId,
(left,right) => left);
这种方式适用于不同场景。
答案 3 :(得分: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;