【问题标题】:Unable to create a constant value of type 'IdentityUserRole'. Only primitive types or enumeration types are supported无法创建“IdentityUserRole”类型的常量值。仅支持原始类型或枚举类型
【发布时间】:2014-11-16 20:55:28
【问题描述】:

在我的 ASP.NET MVC 5 应用程序中,我想列出用户的角色。我下载了一些似乎被破坏的样本。基本上我想要选定用户(不是当前用户!)的角色 ID 和角色名称。

ApplicationUser.Roles 给了我一个只有 RoleId 和 UserId 的 IdentityUserRole 对象。

ApplicationDbContext.Roles 为我提供了一个 IdentityRole,其中包含所有应用程序角色的 RoleId、RoleName 等。

所以我想要的是一个包含两个集合交集的结果集,同时保留完整的角色信息,以便我可以同时使用其角色 ID 和角色名称。

我尝试了 Intersect() 但没有奏效,因为两个对象的类型不同。我尝试了愚蠢的迭代风格,但遇到了一个异常,说数据阅读器已经处于活动状态,所以我很难过:(

我在 LinQPad 上尝试了以下操作(使用适当的连接和命名空间):

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 项),它的转储都会发生。在这种情况下我得到的错误是

“无法创建类型为 'Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole' 的常量值。在此上下文中仅支持原始类型或枚举类型”。

【问题讨论】:

  • 你有没有试过做而不是选择角色,选择新的IdentityRole { Id = role.Id, Name = role.Name }.ToList();
  • 您介意将其中一个答案标记为已接受,这样就不会将这个问题推到首页吗?

标签: linq asp.net-mvc-5 asp.net-identity asp.net-identity-2


【解决方案1】:

您可以结合使用您尝试过的两种方法,从ApplicationUserRoles 属性中存在的上下文中获取角色...

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

【讨论】:

  • 在 LinqPad 中尝试过,但与上面相同,当我尝试列出值时,我得到“无法创建类型的常量值...”NotSUpportedException。
【解决方案2】:

你可以这样做:

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

这种方式适用于不同的场景。

【讨论】:

    【解决方案3】:

    这里唯一的问题是您没有调用ToList() 立即执行查询的方法(所有内容都将保存在内存中)。

    为了更好地理解 - ToList() 方法将 IEnumerable&lt;T&gt; 转换为 List&lt;T&gt;

    因此,您的代码将如下所示:

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

    【讨论】:

      【解决方案4】:

      您正在尝试使用IQueryableallroles 加入内存列表myroles,这会产生一个新的IQueryablelist。但是,这个新的IQueryable 被翻译成SQL,所以myroles 也必须被翻译成SQL。非原始类型的列表不支持此操作。

      解决办法是加入两个IQueryables:

      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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多