建网站合同,我是做网站的 哪里有单接,网站备案的作用,网站建设 环保 图片文章目录 原理实现应用测试 之前我们实现了Employee#xff0c;Alarm管理模块以及通用查询应用层。 Employee的集合查询业务#xff0c;是通过重写CreateFilteredQueryAsync方法#xff0c;来实现按组织架构查询的过滤条件。
我们将这段逻辑代码提取到通用查询应用层中Alarm管理模块以及通用查询应用层。 Employee的集合查询业务是通过重写CreateFilteredQueryAsync方法来实现按组织架构查询的过滤条件。
我们将这段逻辑代码提取到通用查询应用层中便可实现在任何业务的按组织架构查询。
原理
查询依据
在Abp中组织架构和用户是通过中间表AbpUserOrganizationUnits实现多对多的关系。模型如下图所示 查询目标业务对象HealthAlarm关联了业务用户HealthClient因业务用户与鉴权用户IdentityUser共享同一个Id因此可以通过查询组织架构关联的User查询到业务对象。
通过LINQ查询
EmployeeAppService中CreateFilteredQueryAsync方法组织架构的过滤条件代码如下
var organizationUnitUsers await organizationUnitAppService.GetOrganizationUnitUsersAsync(new GetOrganizationUnitUsersInput()
{Id input.OrganizationUnitId.Value
});
if (organizationUnitUsers.Count() 0)
{var ids organizationUnitUsers.Select(c c.Id);query query.Where(t ids.Contains(t.Id));
}
else
{query query.Where(c false);
}通过反射和动态Lambda表达式查询
CreateFilteredQueryAsync是通过业务用户的IRepository获取实体的IQueryable 然后通过query.Where()实现了按组织架构的过滤条件。
IQueryable是一泛型类接口泛型参数是实体类。要想在任意实体实现Where的过滤条件我们使用动态拼接语言集成查询 (LINQ) 的方式实现通用查询接口有关LINQ表达式请阅读 LINQ 教程和有关 Lambda 表达式的文章。
实现
定义按组织架构查询过滤器IOrganizationOrientedFilter接口查询实体列表Dto若实现该接口将筛选指定 OrganizationUnitId 下的用户关联的实体。
public interface IOrganizationOrientedFilter
{Guid? OrganizationUnitId { get; set; }
}重写CreateFilteredQueryAsync方法代码如下 protected override async TaskIQueryableTEntity CreateFilteredQueryAsync(TGetListInput input)
{var query await ReadOnlyRepository.GetQueryableAsync();query await ApplyOrganizationOrientedFiltered(query,input);return query;
}对于OrganizationUnit服务其依赖关系在应用层查找指定组织架构的用户将在CurdAppServiceBase的子类实现。创建一个抽象方法GetUserIdsByOrganizationAsync
protected abstract TaskIEnumerableGuid GetUserIdsByOrganizationAsync(Guid organizationUnitId)创建应用过滤条件方法ApplyOrganizationOrientedFiltered在此实现拼接LINQ表达式代码如下
protected virtual async TaskIQueryableTEntity ApplyOrganizationOrientedFiltered(IQueryableTEntity query, TGetListInput input)
{if (input is IOrganizationOrientedFilter HasPropertyTEntity(UserId)){var property typeof(TEntity).GetProperty(UserId);var filteredInput input as IOrganizationOrientedFilter;if (filteredInput ! null filteredInput.OrganizationUnitId.HasValue){var ids await GetUserIdsByOrganizationAsync(filteredInput.OrganizationUnitId.Value);Expression originalExpression null;var parameter Expression.Parameter(typeof(TEntity), p);foreach (var id in ids){var keyConstantExpression Expression.Constant(id, typeof(Guid));var propertyAccess Expression.MakeMemberAccess(parameter, property);var expressionSegment Expression.Equal(propertyAccess, keyConstantExpression);if (originalExpression null){originalExpression expressionSegment;}else{originalExpression Expression.Or(originalExpression, expressionSegment);}}var equalExpression originalExpression ! null ?Expression.LambdaFuncTEntity, bool(originalExpression, parameter): p false;query query.Where(equalExpression);}}return query;
}请注意可应用过滤的条件为
input需实现IOrganizationOrientedFilter接口实体必须包含UserId字段
否则将原封不动返回IQueryable对象。
应用
在上一章Alarm管理模块中我们已经写好了AlarmAppService我们需要为其实现GetUserIdsByOrganizationAsync方法。改造AlarmAppService代码如下
public class AlarmAppService : ExtendedCurdAppServiceBaseMatoapp.Health.Alarm.Alarm, AlarmDto, AlarmDto, AlarmBriefDto, long, GetAllAlarmInput, GetAllAlarmInput, CreateAlarmInput, UpdateAlarmInput, IAlarmAppService
{private readonly IOrganizationUnitAppService organizationUnitAppService;public AlarmAppService(IOrganizationUnitAppService organizationUnitAppService,IRepositoryMatoapp.Health.Alarm.Alarm, long basicInventoryRepository) : base(basicInventoryRepository){this.organizationUnitAppService organizationUnitAppService;}protected override async TaskIEnumerableGuid GetUserIdsByOrganizationAsync(Guid organizationUnitId){var organizationUnitUsers await organizationUnitAppService.GetOrganizationUnitUsersAsync(new GetOrganizationUnitUsersInput(){Id organizationUnitId});var ids organizationUnitUsers.Select(c c.Id);return ids;}
}在GetAllAlarmInput中实现IOrganizationOrientedFilter接口代码如下
public class GetAllAlarmInput : PagedAndSortedResultRequestDto, IOrganizationOrientedFilter
{public Guid? OrganizationUnitId { get; set; }...
}
测试
创建一些组织架构命名“群组” 在不同“群组”下创建一些客户Client 在告警管理页面中创建一些告警并将这些告警分配给不同的客户 在客户管理中通过选择不同的组织架构查询当前“群组”下的客户告警