ABP.IO:如何无需分页获取ReadOnlyAppService的全部数据?
问题描述
我通过ReadOnlyAppService将NetworkDevice对象暴露给Angular前端,编写的AppService如下:
public class NetworkDeviceAppService: ReadOnlyAppService<NetworkDevice, NetworkDeviceDto, Guid>, INetworkDeviceAppService { public NetworkDeviceAppService(IReadOnlyRepository<NetworkDevice, Guid> repository) : base(repository) { } }
但Angular客户端调用时必须传入PagedAndSortedResultRequestDto才能获取数据:
private getNetworkDevices() { let request = new PagedAndSortedResultRequestDto(); this.networkDeviceService .getList(request) .subscribe(res => { this.networkDevices = res.items; }) }
我不想指定maxResultCount,希望直接获取全部数据,目前想到的方案都不够优雅:
- 传入
2000000作为maxResultCount - 在
NetworkDeviceAppService中添加public async Task<IListResult<NetworkDeviceDto>> GetAllAsync()方法 - 在客户端循环请求数据
想知道是否存在无需PagedAndSortedResultRequestDto的等效ReadOnlyAppService,或者更优雅的实现方式?
优雅实现方案
方案1:重写GetListAsync,兼容无分页逻辑
利用ABP框架的扩展能力,重写基类的GetListAsync方法,通过约定值(比如-1)触发全量数据返回,既保留原有分页逻辑的兼容性,又能实现无分页获取:
public class NetworkDeviceAppService: ReadOnlyAppService<NetworkDevice, NetworkDeviceDto, Guid>, INetworkDeviceAppService { public NetworkDeviceAppService(IReadOnlyRepository<NetworkDevice, Guid> repository) : base(repository) { } public override async Task<PagedResultDto<NetworkDeviceDto>> GetListAsync(PagedAndSortedResultRequestDto input) { // 当maxResultCount为-1时,返回全部数据 if (input.MaxResultCount == -1) { var entities = await Repository.GetListAsync(); var dtos = ObjectMapper.Map<List<NetworkDevice>, List<NetworkDeviceDto>>(entities); return new PagedResultDto<NetworkDeviceDto>(dtos.Count, dtos); } // 否则沿用原有分页逻辑 return await base.GetListAsync(input); } }
前端调用时只需传入约定值:
private getNetworkDevices() { let request = new PagedAndSortedResultRequestDto(); request.maxResultCount = -1; // 标记获取全量数据 this.networkDeviceService .getList(request) .subscribe(res => { this.networkDevices = res.items; }) }
方案2:添加标准全量获取接口
如果希望明确区分分页和全量接口,可以添加符合ABP规范的GetAllAsync方法,借助框架的自动映射能力保证代码简洁:
public class NetworkDeviceAppService: ReadOnlyAppService<NetworkDevice, NetworkDeviceDto, Guid>, INetworkDeviceAppService { public NetworkDeviceAppService(IReadOnlyRepository<NetworkDevice, Guid> repository) : base(repository) { } public async Task<IListResult<NetworkDeviceDto>> GetAllAsync() { var entities = await Repository.GetListAsync(); var dtos = ObjectMapper.Map<List<NetworkDevice>, List<NetworkDeviceDto>>(entities); return new ListResultDto<NetworkDeviceDto>(dtos); } }
同时在接口中声明该方法:
public interface INetworkDeviceAppService : IReadOnlyAppService<NetworkDeviceDto, Guid> { Task<IListResult<NetworkDeviceDto>> GetAllAsync(); }
前端直接调用新接口即可:
private getNetworkDevices() { this.networkDeviceService .getAll() .subscribe(res => { this.networkDevices = res.items; }) }
方案3:封装通用全量只读基类
如果多个业务服务都需要全量获取能力,可以封装通用基类避免重复代码:
public class FullReadOnlyAppService<TEntity, TEntityDto, TKey> : ReadOnlyAppService<TEntity, TEntityDto, TKey> where TEntity : class, IEntity<TKey> where TEntityDto : IEntityDto<TKey> { public FullReadOnlyAppService(IReadOnlyRepository<TEntity, TKey> repository) : base(repository) { } public virtual async Task<IListResult<TEntityDto>> GetAllAsync() { var entities = await Repository.GetListAsync(); var dtos = ObjectMapper.Map<List<TEntity>, List<TEntityDto>>(entities); return new ListResultDto<TEntityDto>(dtos); } }
后续业务服务直接继承该基类即可:
public class NetworkDeviceAppService: FullReadOnlyAppService<NetworkDevice, NetworkDeviceDto, Guid>, INetworkDeviceAppService { public NetworkDeviceAppService(IReadOnlyRepository<NetworkDevice, Guid> repository) : base(repository) { } }
内容的提问来源于stack exchange,提问作者Damien R
相关产品推荐
相关产品推荐

