根据某些条件与另一个表连接后设置 IQueryable<T> 中的属性值
Posted
技术标签:
【中文标题】根据某些条件与另一个表连接后设置 IQueryable<T> 中的属性值【英文标题】:Set value of property in IQueryable<T> after join with another table based on some conditions 【发布时间】:2020-01-15 08:32:58 【问题描述】:我正在为 WPF 实施授权。我有与屏幕绑定的权限。例如,有一个屏幕叫做 floor。它有四个与之关联的权限。
-
查看楼层
添加楼层
编辑楼层
删除楼层
除了每个权限,我们还有四个级别的权限。
-
全部
自我
角色
用户
因此,如果用户拥有权限级别为 ALL 的 View Floor 权限。他们可以查看任何用户创建的所有楼层。
如果用户有 Self 权限级别。他们只能查看自己创建的楼层。
如果用户的权限级别为 Role。他们可以查看根据指定角色分配的所有楼层。
权限级别的角色分配如下:
Roles: Supervisor, Technician
如果 BranchManager 具有上述权限级别。然后,他可以查看自己创建的楼层以及具有主管或技术人员角色的任何用户创建的楼层。
权限级别 User 与 Role 相同。
这是获取楼层的 IQueryable:
IQueryable<FloorModel> FloorsQueryable = (from f in Floors
join b in Branches on f.BranchId equals b.Id
where (string.IsNullOrEmpty(filters.Name) || f.Name.ToLower().Contains(filters.Name.ToLower()))
&& (string.IsNullOrEmpty(filters.BranchName) || b.Name.ToLower().Contains(filters.BranchName.ToLower()))
&& (f.IsDeleted == null || f.IsDeleted == false)
&& f.BranchId == CurrentBranchId
&& f.ApplicationId == CurrentApplicationId
select new FloorModel
Id = f.Id,
Name = f.Name,
Code = f.Code,
Branch = new BranchBriefModel()
Id = f.BranchId,
Name = b.Name,
,
IsActive = f.IsActive ?? false,
Description = f.Description,
CreatedBy = f.CreatedBy ?? 0,
ApplicationId = CurrentApplicationId,
).AsQueryable();
在此之后,我需要根据权限级别对此查询应用一些自定义过滤器
FloorsQueryable = CustomFilter(FloorsQueryable,CurrentUserId,filters);
自定义过滤器代码
public IQueryable<T> CustomFilter<T>(IQueryable<T> query, int CurrentUserId, BaseSearchModel search) where T : BaseModel, new()
var distinctClaims = search.ScreenPermission.Select(x => x.Claim.PermissionLevel).Distinct().ToList();
var viewPermission = search.ScreenPermission.Where(x => x.Name.Contains("View")).FirstOrDefault();
if (viewPermission != null && viewPermission.Claim.PermissionLevel != PermissionLevelCatalog.All)
if (distinctClaims.Any(x => x == PermissionLevelCatalog.Role))
query = (from q in query
join ur in UsersInRoles on q.CreatedBy equals ur.UserId
join r in Roles on ur.RoleId equals r.Id
select q);
string propertyName = "CreatedBy";
//if (string.IsNullOrEmpty(propertyName))
// return query;
// we have parameter "generic"
var selectorParameter = Expression.Parameter(typeof(T), "generic");
// constant "CurrentUserId"
var searchTermExpression = Expression.Constant(CurrentUserId);
// "generic.CreatedBy"
var selector = Expression.PropertyOrField(selectorParameter, propertyName);
// "generic.CreatedBy == "CurrentUserId"
var equal = Expression.Equal(selector, searchTermExpression);
// generic => generic.Name == "CurrentUserId"
var genericWhere = Expression.Lambda<Func<T, bool>>(equal, selectorParameter);
query = query.Where(genericWhere);
return query;
现在对于权限级别 Role,我需要在 IQueryable 的 select 子句中添加 CreatorRoleId 以在以下代码中应用所需的检查。
if (distinctClaims.Any(x => x == PermissionLevelCatalog.Role))
query = (from q in query
join ur in UsersInRoles on q.CreatedBy equals ur.UserId
join r in Roles on ur.RoleId equals r.Id
select q
);
是否可以设置 CreatorRoleId 的值?像下面这样的东西
select q=>q.CreatorRoleId=r.Id return q;
这应该是通用的并且可以为任何 IQueryable 运行。我不想为项目中的所有查询加入 Role 和 UserInRole 表,因为只有当某些用户具有此 Role 权限级别时才需要这些连接。
【问题讨论】:
你做了所有艰苦的工作,因为这个想法很简单! Select(x=> new CreatorRoleId=r.Id );如果这是您需要的,请告诉我 @AsımGündüz 我已经在 Iqueryable 中选择了一些项目。我需要在已选择的项目中设置此属性。这将覆盖之前选择的属性。 只需添加其他选定的字段或输入您的原始选择语句如下,用逗号分隔它们,您也可以给它们别名 Select(x=> new CreatorRoleId=r.Id , field1, field2,ALIASNAME=r.Id); @AsımGündüz 我不知道选择其 IqueryableSelect
?基于角色动态添加Where
过滤器的整个想法不是吗?比显示的x.CreatedBy == CurrentUserId
稍微复杂一点,但仍然是Where
,而不是Select
。
【参考方案1】:
我想这类似于return query.Where(q => q.CreatorRoleId == r.Id);
。
【讨论】:
以上是关于根据某些条件与另一个表连接后设置 IQueryable<T> 中的属性值的主要内容,如果未能解决你的问题,请参考以下文章