怎样优雅地增删查改(七):按用户查询

@

实现

定义按用户查询(IUserOrientedFilter)接口

public interface IUserOrientedFilter
{
    public string EntityUserIdIdiom { get; }
    Guid? UserId { get; set; }
}

  • EntityUserIdIdiom:语义上的UserId,用于指定业务实体中用于描述“用户Id”字段的名称,若不指定,则默认为“UserId”
  • UserId:用户Id,若为Guid.Empty,则使用当前登录用户的Id

查询实体列表Dto若实现该接口,将筛选指定 UserId 下的关联的实体。

若指定 UserId 为 Guid.Empty,则使用当前登录用户的 UserId。

ICurrentUser是Abp的一个服务,用于获取当前登录用户的信息

创建应用过滤条件方法:ApplyUserOrientedFiltered,在此实现拼接LINQ表达式,代码如下:

protected virtual IQueryable<TEntity> ApplyUserOrientedFiltered(IQueryable<TEntity> query, TGetListInput input)
{
    if (input is IUserOrientedFilter)
    {
        var filteredInput = input as IUserOrientedFilter;
        var entityUserIdIdiom = filteredInput.EntityUserIdIdiom;
        if (string.IsNullOrEmpty(entityUserIdIdiom))
        {
            entityUserIdIdiom = "UserId";
        }
        if (HasProperty<TEntity>(entityUserIdIdiom))
        {
            var property = typeof(TEntity).GetProperty(entityUserIdIdiom);
            if (filteredInput != null && filteredInput.UserId.HasValue)
            {
                Guid userId = default;
                if (filteredInput.UserId.Value == Guid.Empty)
                {
                    using (var scope = ServiceProvider.CreateScope())
                    {
                        var currentUser = scope.ServiceProvider.GetRequiredService<ICurrentUser>();
                        if (currentUser != null)
                        {
                            userId = currentUser.GetId();
                        }
                    }
                }
                else
                {
                    userId = filteredInput.UserId.Value;
                }

                var parameter = Expression.Parameter(typeof(TEntity), "p");
                var keyConstantExpression = Expression.Constant(userId, typeof(Guid));

                var propertyAccess = Expression.MakeMemberAccess(parameter, property);
                var expression = Expression.Equal(propertyAccess, keyConstantExpression);

                var equalExpression = expression != null ?
                        Expression.Lambda<Func<TEntity, bool>>(expression, parameter)
                        : p => false;

                query = query.Where(equalExpression);
            }
        }
    }
    return query;
}


请注意,可应用过滤的条件为:

  1. input需实现IUserOrientedFilter接口;
  2. 实体必须关联用户。

否则将原封不动返回IQueryable对象。

使用

无需在应用层中更改代码,

在GetAllAlarmInput中实现IUserOrientedFilter接口,代码如下:

public class GetAllAlarmInput : PagedAndSortedResultRequestDto, IUserOrientedFilter
{
    Guid? UserId { get; set; }
    
    public string EntityUserIdIdiom { get; }      
    // 或显式实现   
    // public string EntityUserIdIdiom => "UserId";
    
    ...
}

测试

创建一些组织架构,命名“群组”

在这里插入图片描述

在不同“群组”下创建一些客户(Client)

在这里插入图片描述

在这里插入图片描述

在告警管理页面中,创建一些告警,并将这些告警分配给不同的客户

在这里插入图片描述

告警创建完成后,进入客户管理,在右侧客户列表中点击“查看详情”

打开客户详情页面,点击“告警”标签页,可以看到该客户下的告警列表

在这里插入图片描述

posted @ 2023-07-18 11:30  林晓lx  阅读(488)  评论(0编辑  收藏  举报