Índice |
---|
Em grande parte de nosso sistema, muitas telas precisam conter apenas uma lógica de CRUD básica (
CrudAppService e AsyncCrudAppService Classes
Se você precisa criar um serviço de aplicação que terá uma operação de CRUD (acrônimo de Create, Read, Update e Delete) para uma entidade especifica.
Visando uma maior produtividade, o TNF contém duas classes para agilizar esses processo: CrudAppService e AsyncCrudAppService.
Como essas classes são facilitadores, neste modelo não possui nenhuma implementação na camada de domínio. As validações são geradas em cima dos objetos que fazem o mapeamento com o banco de dados (Country) e DTOs (CountryDto).
trás classes que agilizam essa criação de serviços de forma automática.
Para utilizar essas funcionalidades instale via nuget o pacote Tnf.App.EntityFrameworkCore disponível em: https://www.myget.org/F/tnf/api/v3/index.json
Primeiro vamos criar nossa interface para o serviço de aplicação definindo sua herança para a interface IAppApplicationService<PersonDto, GetAllPeopleDto> informando qual o Dto será usado para o mapeamento da entidade, e qual o Dto para métodos de GetAllA entidade abaixo realiza o mapeamento da tabela Countries para o Entity Framework Core:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
public interface IPersonAppService : IAppApplicationService<PersonDto, GetAllPeopleDto>
{
} |
Dto:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
[AutoMap(typeof(CountryDto))] [Table("Countries")] public class CountryPersonDto : EntityDtoBase { public conststatic intPersonDto MaxNameLengthNullInstance = 256; [Required] [MaxLength(MaxNameLength)] new PersonDto().AsNullable(); public string Name { get; set; } public enum Error { GetAllPeople = 1, GetPerson = 2, PostPerson = 3, PutPerson = 4, DeletePerson = 5 } } |
Entidade:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
[AutoMap(typeof(CountryDto))] public class Person : Entity { public string Name { get; set; } public CountryPerson() { } public CountryPerson(int id, string name) { Id = id; Name = name; } } |
...
public enum Error
{
PersonNameMustHaveValue = 1
}
} |
Até este ponto temos nossa definição de serviço (interface), Dto criado e Entidade no Entity Framework Core representada.
Essa especificação garante que ao utilizar o serviço de CRUD irá usar o Mapper automático das propriedades pra classe de infraestrutura e Dto.
Para utilizar o AutoMapper consulte o tópico de Mapeamento Automático de Entidades.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
public class CountryDtoPersonAppService : AppApplicationService, CustomValidateIPersonAppService { private readonly IAppDomainService<Person> _service; public string Name { get; set;PersonAppService(IAppDomainService<Person> service) { _service = service; } public override void AddValidationErrors(CustomValidationContext context IListDto<PersonDto, int> GetAll(GetAllPeopleDto request) => _service.GetAll<PersonDto>(request, p => request.Name.IsNullOrEmpty() || p.Name.Contains(request.Name)); public PersonDto Get(IRequestDto<int> id) { ValidateRequestDto(id, nameof(id)); if (string.IsNullOrWhiteSpace(Name)) Notification.HasNotification()) return PersonDto.NullInstance; var entity = _service.Get(id); return entity.MapTo<PersonDto>(); } public PersonDto Create(PersonDto person) { ValidateDto(person, nameof(person)); if context.Results.Add(new ValidationResult("Name is required")); (Notification.HasNotification()) return PersonDto.NullInstance; var personBuilder = new PersonBuilder(Notification) .WithId(person.Id) .WithName(person.Name); person.Id } } } |
Definição da interface do serviço de aplicação:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
public interface ICountryAppService : IAsyncCrudAppService<CountryDto>
{
} |
Implementação do serviço de aplicação informando qual a entidade, DTO e realizando a herança da classe AsyncCrudAppService que irá definir que este serviço contem as funcionalidades de CRUD presentes no TNF:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
public class CountryAppService : AsyncCrudAppService<Country, CountryDto>, ICountryAppService { public CountryAppService(IRepository<Country> repository) = _service.InsertAndGetId(personBuilder); return person; } public PersonDto Update(int id, PersonDto person) { ValidateDtoAndId(person, id, nameof(person), nameof(id)); if (Notification.HasNotification()) return PersonDto.NullInstance; var personBuilder = new PersonBuilder(Notification) .WithId(id) .WithName(person.Name); _service.Update(personBuilder); person.Id = id; return person; } public void Delete(int id) { ValidateId(id, nameof(id)); : base(repositoryif (Notification.HasNotification()) { return; _service.Delete(id); } } |
Note que o serviço recebe como parâmetro um repositório de dados para a entidade Country. Quem define a implementação para a interface IRepository neste exemplo é um nuget package do TNF que contém uma implementação de repositório para o Entity Framework Core chamado: "Tnf.App.EntityFrameworkCore".
O repositório padrão realiza o mapeamento da entidade automaticamente para o seu respectivo DTO através de outros pacotes chamados: Tnf.AutoMapper e Tnf.Dto.
a definição do serviço se da pela herança da classe IAppDomainService<Person> onde é passado a Entidade do Entity Framework Core.
Após a definição acima o serviço de aplicação pode ser usado normalmente.
A interface IAppApplicationService<PersonDto, GetAllPeopleDto> expõe os métodos de CRUD no formato síncrono. Também existe a versão assíncrona do serviço de CRUD usando a interface IAppAsyncApplicationService<PersonDto, GetAllPeopleDto>.Ambos os pacotes podem ser obtidos através de nosso feed de pacotes: https://www.myget.org/F/tnf/api/v3/index.json