abp自动建立crud服务-CrudAppService 和 AsyncCrudAppService
4.1.3 CrudAppService 和 AsyncCrudAppService
如果你想为某个特定的实体创建基于CRUD的应用服务,该服务具有这些方法:Create,Delete,Get,GetAll;那么﴾为了方便
快捷﴿,我们可以继承 CrudAppService﴾或者 AsyncCrudAppService 如果你想要创建async方法﴿类来简单实现这些功能。
CrudAppService 是一个可扩展的泛型基类,该类的泛型参数是对指定实体操作与之相关的 Entity和DTO 类,并且你可以根据
你的需要自定义覆盖基类的功能。
关于CRUD的简单应用服务示例
假设我们有一个任务实体的定义,如下所示:
public class Task : Entity, IHasCreationTime
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreationTime { get; set; }
public TaskState State { get; set; }
public Person AssignedPerson { get; set; }
public Guid? AssignedPersonId { get; set; }
public Task()
{
CreationTime = Clock.Now;
State = TaskState.Open;
}
}
然后,我们为该实体创建一个DTO:
[AutoMap(typeof(Task))]
public class TaskDto : EntityDto, IHasCreationTime
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreationTime { get; set; }
public TaskState State { get; set; }
public Guid? AssignedPersonId { get; set; }
public string AssignedPersonName { get; set; }
}
使用AutoMap特性,自动创建实体和DTO的映射配置。那么,我们可以创建一个应用服务,如下所示:
public class TaskAppService : AsyncCrudAppService<Task, TaskDto>
{
public TaskAppService(IRepository<Task> repository)
: base(repository)
{ }
}
我们注入了仓储并且传递该参数给基类﴾如果我们想要创建 sync 方法来替代 async 方法,那么我们可以继承自
CrudAppService﴿。。好了,现在 TaskAppService 就有了简单的CRUD方法了。如果你想为你的应用服务定义一个接口,那么
如下所示:
public interface ITaskAppService : IAsyncCrudAppService<TaskDto>
{ }注意:IAsyncCrudAppService 接口不会取得实体﴾Task﴿作为泛型参数。因为,实体与之相关的实现不应该包括在公共接口里
面。现在,我们可以在 TaskAppService 类中实现 ITaskAppService 接口。如下所示:
public class TaskAppService : AsyncCrudAppService<Task, TaskDto>, ITaskAppService
{
public TaskAppService(IRepository<Task> repository)
: base(repository)
{ }
}
为应用服务自定义CRUD
Getting List
CRUD 应用服务使用 PagedAndSortedResultRequestDto 作为方法 GetAll 的默认参数,该参数提供了可选的排序和分页参
数。但是你可能想添加其他参数到GetAll方法。例如,你可能想添加某些自定义的过滤。这样的话,你可以为GetAll方法创建一
个DTO。如下所示:
public class GetAllTasksInput : PagedAndSortedResultRequestDto
{
public TaskState? State { get; set; }
}
我们继承 PagedAndSortedResultRequestInput 类﴾当然这不是必须的,如果你想要使用基类的分页和排序参数的话﴿并且添加
一个可选的 State 属性,通过State属性来过滤Task。现在,为了能够应用自定义过滤,我们应该改变 TaskAppService。如下所
示:
public class TaskAppService : AsyncCrudAppService<Task, TaskDto, int, GetAllTasksInput>
{
public TaskAppService(IRepository<Task> repository)
: base(repository)
{ } p
rotected override IQueryable<Task> CreateFilteredQuery(GetAllTasksInput input)
{
return base.CreateFilteredQuery(input)
.WhereIf(input.State.HasValue, t => t.State == input.State.Value);
}
}
首先,我们添加了 GetAllTasksInput 作为第4个泛型参数到AsyncCrudAppService类﴾第三个参数是实体的主键﴿。然后,重写
CreateFilteredQuery 方法来应用自定义过滤。这个方法是作为 AsyncCrudAppService 类的一个扩展点﴾为了简化条件过滤,我
们使用了ABP的一个扩展方法WhereIf,但实际上我们所做的就是对IQueryable的过滤﴿。
注意:如果你已经创建应用服务的接口,那么你也需要为该接口添加泛型参数。
Create和Update
注意:我们使用相同的DTO﴾TaskDto﴿去取得,创建以及更新任务;但是在实际的应用中,这样使用可能不太好。所以,我们需
要 自定义创建和更新DTOs。首先,我们创建一个 CreateTaskInput 类:
[AutoMapTo(typeof(Task))]
public class CreateTaskInput
{
[Required]
[MaxLength(Task.MaxTitleLength)]
public string Title { get; set; }
[MaxLength(Task.MaxDescriptionLength)]
public string Description { get; set; }
public Guid? AssignedPersonId { get; set; }
}然后创建一个 UpdateTaskInput DTO:
[AutoMapTo(typeof(Task))]
public class UpdateTaskInput : CreateTaskInput, IEntityDto
{
public int Id { get; set; }
public TaskState State { get; set; }
}
对于更新操作,我想要继承 CreateTaskInput 类,这样会包括该类的所有属性。在这里扩展 IEntity ﴾或者对于其他类型的主键
可以扩展IEntity<PrimaryKey>接口﴿ 是必须﴾Required﴿的;因为,我们需要知道那个实体需要更新。最后,我还添加了一个不在
CreateTaskInput类中的属性 State。
现在,我们可以使用这些DTO类来作为 AsyncCrudAppService 类的泛型参数,如下所示:
public class TaskAppService : AsyncCrudAppService<Task, TaskDto, int, GetAllTasksInput, CreateTaskInput, UpdateTaskInput
{
public TaskAppService(IRepository<Task> repository)
: base(repository)
{ } p
rotected override IQueryable<Task> CreateFilteredQuery(GetAllTasksInput input)
{
return base.CreateFilteredQuery(input)
.WhereIf(input.State.HasValue, t => t.State == input.State.Value);
}
}
我们不需要添加额外的代码来做出更改。
其他方法参数
如果你想要为 Get和Delete 方法自定义input DTOs 参数,那么就要为AsyncCrudAppService类能设置更多的泛型参数。那么,
所有的基类方法都是virtual,这样你就可以重写或者自定义这些行为。
4.1.4 CRUD 权限
你可能需要授权给CRUD方法。ABP中有一些预定义的权限属性可以设置:GetPermissionNam,GetAllPermissionName,
CreatePermissionName,UpdatePermissionName 和 DeletePermissionName。如果设置了它们,那么基于CRUD的类会自动检
测权限。你可以在构造函数设置它们,如下所示:
public class TaskAppService : AsyncCrudAppService<Task, TaskDto>
{
public TaskAppService(IRepository<Task> repository)
: base(repository)
{
CreatePermissionName = "MyTaskCreationPermission";
}
}
或者,你可以重写权限检测方法来手动检测权限:CheckGetPermission﴾﴿, CheckGetAllPermission﴾﴿,
CheckCreatePermission﴾﴿,CheckUpdatePermission﴾﴿,CheckDeletePermission﴾﴿。它们都是用相应的权限名称来调用
CheckPermission﴾...﴿方法,其实就是调用IPermissionChecker.Authorize﴾...﴿方法。
浙公网安备 33010602011771号