六、仓储
仓储是领域层和数据映射层的中介,用类似集合的接口存取领域对象。
用来操作数据库进行数据存取,仓储接口定义在领域层core并继承IRepository接口,实现类在基础设施层Entityframeworkcore。
仓储类实现IRepository接口,接口定义了常用的同步和异步的增删改查方法。
针对EntityFramework提供了EfRepositoryBase<TDbContext, TEntity, TPrimaryKey>的泛型版本的实现方法,被xxRepositoryBase继承。
namespace MyAbpProject.Demo
{
[Table("Task")]
public class TasksEntity : Entity, IHasCreationTime
{
public const int MaxTitleLength = 256;
public const int MaxDescriptionLength = 64 * 1024;//64Kb
public long? AssignedPersonId { get; set; }
[Required]
[MaxLength(MaxTitleLength)]
public string Title { get; set; }
[Required]
[MaxLength(MaxDescriptionLength)]
public string Description { get; set; }
public TaskState State { get; set; }
public DateTime CreationTime { get ; set ; }
public TasksEntity()
{
CreationTime = Clock.Now;
State = TaskState.Open;
}
public TasksEntity(string title, string description = null) : this()
{
Title = title;
Description = description;
}
}
public enum TaskState : byte
{
Open = 0,
Completed = 1
}
}
七、应用服务层
展现层通过传入DTO数据传输对象参数来调用应用服务,应用服务通过领域对象来执行相应的业务逻辑并将DTO返回给展现层。
应用服务接口继承IApplicationService接口,ABP为该接口提供了默认的实现类ApplicationService,该基类提供日志记录和本地化功能。
一个应用服务方法默认为一个工作单元UOW,ABP针对UOW模式自动进行数据库连接和事务管理,且自动保存数据修改。
DTO的好处:数据隐藏;序列化和延迟加载;ABP对DTO提供了约定类以支持验证;参数或返回值的改变,通过Dto方便扩展。命名规范:MethodNameInput、MethodNameOutput
namespace MyAbpProject.Task.Services
{
public class TaskAppService: ApplicationService,ITaskAppService
{
private readonly IRepository<MyAbpProject.Demo.TasksEntity> _taskRepository;
public TaskAppService(IRepository<MyAbpProject.Demo.TasksEntity> taskRepository)
{
_taskRepository = taskRepository;
}
public GetTasksOutput GetTasks(GetTaskInput input)
{
var query = _taskRepository.GetAll();
if (input.AssignedPersonId.HasValue)
{
query = query.Where(t => t.AssignedPersonId == input.AssignedPersonId.Value);
}
if (input.State.HasValue)
{
query = query.Where(t => t.State == input.State.Value);
}
GetTasksOutput result = new GetTasksOutput();
result.Tasks=ObjectMapper.Map<List<TaskDto>>(query.ToList());
return result;
}
public async Task<TaskDto> GetTaskByIdAsync(int taskId)
{
//Called specific GetAllWithPeople method of task repository.
var task = await _taskRepository.GetAsync(taskId);
//Used AutoMapper to automatically convert List<Task> to List<TaskDto>.
return task.MapTo<TaskDto>();
}
public TaskDto GetTasksDataById(int taskId)
{
var task = _taskRepository.Get(taskId);
return task.MapTo<TaskDto>();
}
public void UpdateTask(UpdateTaskInput input)
{
//We can use Logger, it's defined in ApplicationService base class.
Logger.Info("Updating a task for input: " + input);
//Retrieving a task entity with given id using standard Get method of repositories.
var task = _taskRepository.Get(input.Id);
//Updating changed properties of the retrieved task entity.
if (input.State.HasValue)
{
task.State = input.State.Value;
task.AssignedPersonId = input.AssignedPersonId.Value;
task.Title = input.Title;
task.Description = input.Description;
}
}
public int CreateTask(CreateTaskInput input)
{
//We can use Logger, it's defined in ApplicationService class.
Logger.Info("Creating a task for input: " + input);
//Creating a new Task entity with given input's properties
var task = new MyAbpProject.Demo.TasksEntity
{
Description = input.Description,
Title = input.Title,
State = input.Status,
CreationTime = Clock.Now,
AssignedPersonId=input.AssignedPersonId
};
//Saving entity with standard Insert method of repositories.
return _taskRepository.InsertAndGetId(task);
}
public void DeleteTask(int taskId)
{
var task = _taskRepository.Get(taskId);
if (task != null)
{
_taskRepository.Delete(task);
}
}
}
}
namespace MyAbpProject
{
public interface IDtoMapping
{
void CreateMapping(IMapperConfigurationExpression mapperConfig);
}
}
namespace MyAbpProject
{
[DependsOn(
typeof(MyAbpProjectCoreModule),
typeof(AbpAutoMapperModule))]
public class MyAbpProjectApplicationModule : AbpModule
{
public override void PreInitialize()
{
Configuration.Authorization.Providers.Add<MyAbpProjectAuthorizationProvider>();
}
public override void Initialize()
{
var thisAssembly = typeof(MyAbpProjectApplicationModule).GetAssembly();
IocManager.RegisterAssemblyByConvention(thisAssembly);
//注册IDtoMapping
IocManager.IocContainer.Register(
Classes.FromAssembly(Assembly.GetExecutingAssembly())
.IncludeNonPublicTypes()
.BasedOn<IDtoMapping>()
.WithService.Self()
.WithService.DefaultInterfaces()
.LifestyleTransient()
);
//解析依赖,并进行映射规则创建
Configuration.Modules.AbpAutoMapper().Configurators.Add(mapper =>
{
var mappers = IocManager.IocContainer.ResolveAll<IDtoMapping>();
foreach (var dtomap in mappers)
dtomap.CreateMapping(mapper);
});
}
}
}
---------------------------------------------------------
或者:
Configuration.Modules.AbpAutoMapper().Configurators.Add(
// Scan the assembly for classes which inherit from AutoMapper.Profile
cfg => cfg.AddProfiles(thisAssembly)
);
namespace MyAbpProject
{
public class TaskDtoMapping : IDtoMapping
{
public void CreateMapping(IMapperConfigurationExpression mapperConfig)
{
//定义单项映射
mapperConfig.CreateMap<CreateTaskInput, MyAbpProject.Demo.TasksEntity>().ReverseMap();
mapperConfig.CreateMap<UpdateTaskInput, MyAbpProject.Demo.TasksEntity>().ReverseMap();
mapperConfig.CreateMap<TaskDto, MyAbpProject.Demo.TasksEntity>().ReverseMap();
}
}
}
namespace MyAbpProject.Task.Dtos
{
public class TaskDto:EntityDto
{
public long? AssignedPersonId { get; set; }
//public string AssignedPersonName { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreationTime { get; set; }
public TaskState State { get; set; }
public override string ToString()
{
return string.Format(
"[Task Id={0}, Description={1}, CreationTime={2}, AssignedPersonName={3}, State={4}]",
Id,
Description,
CreationTime,
AssignedPersonId,
(TaskState)State
);
}
}
}