代码之家  ›  专栏  ›  技术社区  ›  johey

通过实体框架访问身份声明(带有automapper投影和谓词生成器)

  •  0
  • johey  · 技术社区  · 7 年前

    我似乎在尝试实现不可能的目标:从我的(实体框架)实体的(计算的)属性中,我正在尝试检查登录用户是否具有某种声明。更准确地说,当尝试在LinqDB查询中使用此属性时,它不起作用。

    LINQ查询没有什么特别的:

    var query = DbContext.Organizations.Where(x => !x.DeleteDate.HasValue);
    

    数据检索由 自映射投影 :

    var dto = await query.ProjectToListAsync<MyDto>(Mapper.ConfigurationProvider);
    

    我已将此属性添加到我的组织实体中:

    [Computed]
    public bool CanCancel => !CancelDate.HasValue 
                                 && identity.Claims.Any(c => c.Type == permission.ToString());  // identity is of type ClaimsIdentity, permission is an enum from our project
    

    (The 计算的 属性来自 DelegateCompiler library 它允许将委托或方法体反编译为其lambda表示形式。如果用这个标记实体的方法,automapper可以在投影期间的查询中使用它。 我们在项目中经常使用这种技术,它非常有用!)

    不幸的是,它看起来不像 索赔。索赔 可以反编译。运行代码会引发 错误 :

    无法创建类型为的常量值 “System.Security.Claims.Claim”。仅限基元类型或枚举 在此上下文中支持类型。

    我想这与索赔财产的内部有关:

    public virtual IEnumerable<Claim> Claims
    {
      get
      {
        for (int i = 0; i < this.m_instanceClaims.Count; ++i)
          yield return this.m_instanceClaims[i];
        if (this.m_externalClaims != null)
        {
          for (int j = 0; j < this.m_externalClaims.Count; ++j)
          {
            if (this.m_externalClaims[j] != null)
            {
              foreach (Claim claim in this.m_externalClaims[j])
                yield return claim;
            }
          }
        }
      }
    }
    

    但我看不出我怎么能解决这个问题。 有人有主意吗?

    事先谢谢!

    1 回复  |  直到 7 年前
        1
  •  0
  •   johey    7 年前

    好吧,我没有找到这个问题的完美解决方案,但是我可以通过以下方式解决它:

    a)创建检查声明的静态属性:

    private static bool CanCancel => identity.HasPermission(AppPermission.CanCancel);
    

    (HasPermission是一种扩展方法,它使用ClaimSidentity的HasClaim方法检查标识是否具有给定的权限)

    b)从我的计算属性访问这些属性:

    [Computed] 
    public bool IsCancelable => !CancelDate.HasValue && CanCancel;
    

    由于此属性不再包含输入变量(例如检查权限),Linq to Entities现在可以将其正确转换为查询。

    推荐文章