更改 AsyncCrudAppService 中 GetAll 方法的输出 DTO(return 值)
Changing the output DTO (return value) of the GetAll method in an AsyncCrudAppService
我在我的 AppServices 中使用 ABP 的 AsyncCrudAppService
。这是我的界面:
public interface IAssetRequisitionAppService : IAsyncCrudAppService
<AssetRequisitionDto, Guid, GetAllInput, AssetRequisitionDto, AssetRequisitionDto, AssetRequisitionDetailsDto>
{ }
和服务:
public class AssetRequisitionAppService : AsyncCrudAppService
<AssetRequisition, AssetRequisitionDto, Guid, GetAllInput, AssetRequisitionDto, AssetRequisitionDto, AssetRequisitionDetailsDto>,
IAssetRequisitionAppService
{
public AssetRequisitionAppService(IRepository<AssetRequisition, Guid> repository) : base(repository)
{ }
}
现在,我相信所有这些标准的 CRUD 方法都会 return 默认类型(在我的例子中是 AssetRequisitionDto
)。但是,我想要做的是 return Get()
和 GetAll()
方法的不同类型。
Get()
应该有一个更详细的 DTO,其中包含 Navigation 道具的子属性。但是 GetAll()
应该有一个不那么详细的用于填充 table.
有没有办法以某种方式覆盖 return 类型?
是的,有某种方式。
// using Microsoft.AspNetCore.Mvc;
[ActionName(nameof(GetAll))]
public PagedResultRequestDto MyGetAll(PagedResultRequestDto input)
{
return input;
}
[NonAction]
public override Task<PagedResultDto<UserDto>> GetAll(PagedResultRequestDto input)
{
return base.GetAll(input);
}
参考:https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2859
好吧,我注意到我最终还是需要更复杂的过滤方法。因此,我创建了自定义类型和方法。
首先,我从 PagedAndSortedResultRequestDto
中创建了自己的 GetAllInput
。它适用于我的大部分服务,因为我通常需要查询与员工和位置相关的数据:
public class GetAllInput : PagedAndSortedResultRequestDto
{
public long? PersonId { get; set; }
public long? LocationId { get; set; }
public EEmployeeType? EmployeeType { get; set; }
}
之后,我为每个服务编写了一个 GetAll
方法。它们都是 return 和 PagedResultDto<>
,所以我可以在表示层中使用它的功能。下面是一个示例:
//MovableAppService
public PagedResultDto<MovableLineDto> GetAllLinesRelatedToUser(GetAllInput input)
{
Logger.Info("Loading all movables related to current user");
IQueryable<Movable> queryable = null;
if (input.PersonId.HasValue)
{
if (input.EmployeeType == EEmployeeType.Recorder)
{
var recorder = _personRepository.GetAll()
.OfType<Employee>()
.FirstOrDefault(x => x.Id == input.PersonId);
var authorizedStorageIds = recorder.StoragesAuthorized.Select(y => y.Id);
queryable = _repository.GetAll()
.Where(x => authorizedStorageIds.Contains(x.StorageOfOriginId));
}
else if (input.EmployeeType == EEmployeeType.UnitManager)
{
var locationCodes = _locationRepository.GetAll()
.Where(x => x.ManagerInChargeId == input.PersonId)
.Select(x => x.Code);
foreach (var code in locationCodes)
{
queryable = _locationRepository.GetAll()
.Where(x => x.Code.StartsWith(code))
.SelectMany(x => x.AssignmentDocs)
.SelectMany(x => x.Movements)
.OfType<Assignment>()
.Where(x => x.TimeOfReturn == null)
.Select(x => x.Asset)
.OfType<Movable>();
queryable = queryable.Concat(queryable);
}
}
else if (input.TenantIdsOversee.Count() > 0)
{
var overseer = _personRepository.GetAll()
.OfType<Overseer>()
.FirstOrDefault(x => x.Id == input.PersonId);
var overseeingTenantIds = overseer.TenantsOversee.Select(y => y.Id);
queryable = _repository.GetAll()
.Where(x => overseeingTenantIds.Contains((int)x.TenantId));
}
else if (input.EmployeeType == EEmployeeType.Employee)
{
queryable = _personRepository.GetAll()
.OfType<Employee>()
.Where(x => x.Id == input.PersonId)
.SelectMany(x => x.AssignmentDocs)
.SelectMany(x => x.Movements)
.OfType<Assignment>()
.Where(x => x.TimeOfReturn == null)
.Select(x => x.Asset)
.OfType<Movable>();
}
}
var list = queryable.ToList()
.OrderBy(x => x.Category.Definition);
var items = _objectMapper.Map<IReadOnlyList<MovableLineDto>>(list);
return new PagedResultDto<MovableLineDto>(items.Count, items);
}
顺便说一句,亚伦的回答可能对 ASP.NET Core 项目有效。但是我的项目在 MVC EF6 中,所以这些注释对我来说不可用。
现在我将其标记为答案,但如果有更优雅的方式,我很高兴看到,然后我会更改我的标记。
我在我的 AppServices 中使用 ABP 的 AsyncCrudAppService
。这是我的界面:
public interface IAssetRequisitionAppService : IAsyncCrudAppService
<AssetRequisitionDto, Guid, GetAllInput, AssetRequisitionDto, AssetRequisitionDto, AssetRequisitionDetailsDto>
{ }
和服务:
public class AssetRequisitionAppService : AsyncCrudAppService
<AssetRequisition, AssetRequisitionDto, Guid, GetAllInput, AssetRequisitionDto, AssetRequisitionDto, AssetRequisitionDetailsDto>,
IAssetRequisitionAppService
{
public AssetRequisitionAppService(IRepository<AssetRequisition, Guid> repository) : base(repository)
{ }
}
现在,我相信所有这些标准的 CRUD 方法都会 return 默认类型(在我的例子中是 AssetRequisitionDto
)。但是,我想要做的是 return Get()
和 GetAll()
方法的不同类型。
Get()
应该有一个更详细的 DTO,其中包含 Navigation 道具的子属性。但是 GetAll()
应该有一个不那么详细的用于填充 table.
有没有办法以某种方式覆盖 return 类型?
是的,有某种方式。
// using Microsoft.AspNetCore.Mvc;
[ActionName(nameof(GetAll))]
public PagedResultRequestDto MyGetAll(PagedResultRequestDto input)
{
return input;
}
[NonAction]
public override Task<PagedResultDto<UserDto>> GetAll(PagedResultRequestDto input)
{
return base.GetAll(input);
}
参考:https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2859
好吧,我注意到我最终还是需要更复杂的过滤方法。因此,我创建了自定义类型和方法。
首先,我从 PagedAndSortedResultRequestDto
中创建了自己的 GetAllInput
。它适用于我的大部分服务,因为我通常需要查询与员工和位置相关的数据:
public class GetAllInput : PagedAndSortedResultRequestDto
{
public long? PersonId { get; set; }
public long? LocationId { get; set; }
public EEmployeeType? EmployeeType { get; set; }
}
之后,我为每个服务编写了一个 GetAll
方法。它们都是 return 和 PagedResultDto<>
,所以我可以在表示层中使用它的功能。下面是一个示例:
//MovableAppService
public PagedResultDto<MovableLineDto> GetAllLinesRelatedToUser(GetAllInput input)
{
Logger.Info("Loading all movables related to current user");
IQueryable<Movable> queryable = null;
if (input.PersonId.HasValue)
{
if (input.EmployeeType == EEmployeeType.Recorder)
{
var recorder = _personRepository.GetAll()
.OfType<Employee>()
.FirstOrDefault(x => x.Id == input.PersonId);
var authorizedStorageIds = recorder.StoragesAuthorized.Select(y => y.Id);
queryable = _repository.GetAll()
.Where(x => authorizedStorageIds.Contains(x.StorageOfOriginId));
}
else if (input.EmployeeType == EEmployeeType.UnitManager)
{
var locationCodes = _locationRepository.GetAll()
.Where(x => x.ManagerInChargeId == input.PersonId)
.Select(x => x.Code);
foreach (var code in locationCodes)
{
queryable = _locationRepository.GetAll()
.Where(x => x.Code.StartsWith(code))
.SelectMany(x => x.AssignmentDocs)
.SelectMany(x => x.Movements)
.OfType<Assignment>()
.Where(x => x.TimeOfReturn == null)
.Select(x => x.Asset)
.OfType<Movable>();
queryable = queryable.Concat(queryable);
}
}
else if (input.TenantIdsOversee.Count() > 0)
{
var overseer = _personRepository.GetAll()
.OfType<Overseer>()
.FirstOrDefault(x => x.Id == input.PersonId);
var overseeingTenantIds = overseer.TenantsOversee.Select(y => y.Id);
queryable = _repository.GetAll()
.Where(x => overseeingTenantIds.Contains((int)x.TenantId));
}
else if (input.EmployeeType == EEmployeeType.Employee)
{
queryable = _personRepository.GetAll()
.OfType<Employee>()
.Where(x => x.Id == input.PersonId)
.SelectMany(x => x.AssignmentDocs)
.SelectMany(x => x.Movements)
.OfType<Assignment>()
.Where(x => x.TimeOfReturn == null)
.Select(x => x.Asset)
.OfType<Movable>();
}
}
var list = queryable.ToList()
.OrderBy(x => x.Category.Definition);
var items = _objectMapper.Map<IReadOnlyList<MovableLineDto>>(list);
return new PagedResultDto<MovableLineDto>(items.Count, items);
}
顺便说一句,亚伦的回答可能对 ASP.NET Core 项目有效。但是我的项目在 MVC EF6 中,所以这些注释对我来说不可用。
现在我将其标记为答案,但如果有更优雅的方式,我很高兴看到,然后我会更改我的标记。