Entity Framework Plus动态过滤中断了查找方法

时间:2018-06-04 09:35:48

标签: c# entity-framework entity-framework-6 entity-framework-plus

我需要根据用户的权限动态过滤特定表格中的数据。例如。 "正常"用户只能看到分配给他的记录,但管理员可以看到所有记录。我使用ninject为每个请求创建数据库上下文,并通过将其他用户信息传递给构造函数来创建上下文。然后我从EntityFramework-Plus扩展中应用动态过滤(EF6):

public MyDbContext(bool isAdmin, string userId) : this()
{
    if (!isAdmin)
    {
        this.Filter<MyTable>(table => table.Where(...));
    }
}

此解决方案按预期工作,即调用方法,如:

ctx.MyTable.Where(...)

结果在过滤器中声明了额外的连接。

但是当我使用Find()方法时表现得很奇怪。我正在使用SqlServer探查器来了解幕后发生的事情:

  1. 我创建上下文为受限制(非管理员用户) - 调用Find()将导致对应于过滤器的lambda表达式的额外WHERE语句
  2. 然后我创建上下文作为admin(单独的请求) - 调用Find()将导致相同的SQL表达式(我希望没有额外的SQL子句)。
  3. AFAIK这与查询缓存有关,因为在构造函数中添加额外的行似乎可以解决问题:

    public MyDbContext(bool isAdmin, string userId) : this()
    {
        // this "solves" the problem
        QueryFilterManager.ClearQueryCache(this);
    
        if (!isAdmin)
        {
            this.Filter<MyTable>(table => table.Where(...));
        }
    }
    

    这看起来像是一个很大的矫枉过正,它并没有让我更接近理解这个问题。所以这是我的问题:

    1. 为什么这个问题不影响Where()但影响Find()?
    2. 有没有更清洁的方法来解决这个问题?我已经阅读了有关动态过滤器库的内容,但它对我没有好处,因为它仅适用于代码优先模型(此处为DB)。
    3. 是否有基于每个请求数据过滤数据的更好概念(如我的示例中的userId)?
    4. 更新

      这就是我的lambda表达式:

      private Func<IQueryable<MyTable>, IQueryable<MyTable>> GetFilter(string userId)
          {
              return t => t
                      .Where(c.DataScopes.Any(
                              x => x.AspNetGroups.Any(
                                  ang => ang.AspNetUsers.Any(
                                      anu => anu.Id == userId))));
          }
      

      AspNetGroups是我的自定义表,用于分组用户。数据持久性分配给用户组。

0 个答案:

没有答案