【问题标题】:best way to filter rows by permission in Entity Framework在实体框架中按权限过滤行的最佳方法
【发布时间】:2015-12-21 13:20:30
【问题描述】:

在我的项目中,我有一些帖子,例如 NewsArticleAnnouncement 和 ...

每个帖子都有 Permission ,例如 ID 为 1 的新闻帖子只有管理员用户可以这样做......

如果登录,我应该按用户角色显示帖子。

为此,我尝试了一些方法:

方式 1: 我添加了一个扩展方法来过滤 News,Article , ... 像这样

public static class EfExtensionMethods
{
   public  IEnumerable<News> Filter( IDbSet<News> dbset) 
   {
      return (dbset.Where(...));
   }
}

方式 2: 我为过滤行添加了一个方法到服务层,像这样:

public void FilterNews(IEnumerable<News> newsList)
{
   var roles = _currentUserService.GetCurrentUserRoles();
   if (roles.Count == 0)
   {
      newsList = newsList.Where(...).ToList();
   }
   else
   {
      newsList = newsList.Where(...).ToList();
   }
}

在任何地方我只需要将 NewsList 列表传递给此方法即可进行过滤。 女巫一号被包围了?

有什么最好的方法吗? 我想要一种可重用且不为每个类复制的方法

【问题讨论】:

    标签: c# entity-framework entity-framework-4


    【解决方案1】:

    您应该使用静态Expressions 创建一个静态类,您可以在查询中使用这些类,然后过滤数据库(现在您正在从数据库中获取所有行并丢弃不需要的那些是浪费):

    partial class News
    {
        public static class Q
        {
            public static Expression<Func<News,bool>> HasPermission(int permissionID)
            {
                return expr => expr.PermissionID == permissionID
            }
         }
     }
    

    然后你可以做这样的查询,例如:

    db.News.Where(News.Q.HasPermission(1)).ToList();
    

    您将只从News 表中获取权限等于“1”的行。我真的不知道你的权限是如何存储的,但我想你明白了:)

    编辑:使用泛型,我认为最简单的方法是让您的模型从 Permissionbase 类或其他东西继承:

    public abstract class PermissionBase
    {
       public int PermissionID {get; set;}
    }
    
    public static class QueryExtensions
    {
       public static Expression<Func<T,bool>> HasPermission<T>(int permissionID) where T: PermissionBase
       {
           return expr => expr.PermissionID == permissionID
       }
    }
    

    如果没有基类,也应该可以通过在运行中构建您的Expression

    public static Expression<Func<T, bool>> HasPermission<T>(int PermissionID) where T : class
    {
       ParameterExpression pe = Expression.Parameter(typeof(T), "p");
       System.Reflection.PropertyInfo pi = typeof(T).GetProperty("PermissionID");
       MemberExpression me = Expression.MakeMemberAccess(pe, pi);
       ConstantExpression ce = Expression.Constant(PermissionID);
       BinaryExpression be = Expression.Equal(me, ce);
       return Expression.Lambda<Func<T, bool>>(be, pe);
    }
    

    显然,只要确保所有模型中的属性名都是正确的,或者您可以使用字符串将属性名传递给方法。

    【讨论】:

    • 谢谢,我需要ArticleAnnouncementPoll 的静态代码。我怎样才能写出你的 Method daynamacy。我不会为每个班级复制和过去
    • 我需要按 List 过滤,我该如何更改?以及如何调用 Last code ?
    • 不存在“HasPermisson”NewsList.FirstOrDefault().Permissions.
    【解决方案2】:

    我假设您正在谈论行级安全性。这是一项相当复杂的任务。 有几种方法可以做到这一点。

    对于 MSSQL,请尝试查看 MSDN Security Blog about RLS

    【讨论】:

    • 不,我只需要一种按用户权限过滤行的方法。我写了这个方法,但我想要最好的方法
    猜你喜欢
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    相关资源
    最近更新 更多