Índice |
---|
Para começarmos a trabalhar temos que criar um projeto com suporte a .NET Core.
Para isso através do Visual Studio 2017 vamos criar nosso projeto acessando: File -> New -> Project -> .NET Standard -> Class Library.
Para utilização do provider do Carol, precisamos instalar um pacote chamado Tnf.Provider.Carol disponível em: https://www.myget.org/F/tnf/api/v3/index.json
Podemos agora começar a criar nossa entidade e repositórios para uso do Carol. Vamos começar , começando com a definição de nosso módulo:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using Tnf.App.Carol; using Tnf.App.Carol.Configuration; using Tnf.Modules; using Tnf.Architecture.Domain; using Tnf.Reflection.Extensions; [DependsOn( typeof(DomainModule), typeof(TnfCarolModule))] public class CarolModule : TnfModule { public override void PreInitialize() { Configuration.Modules .TnfCarol() .Configure(new TnfCarolConfig() { ApplicationId = "21af0700038211e79daf4a8136534b63", TenantId = "8cd6e43115e9416eb23609486fa053e3", BaseAddress = "https://totvshealth.carol.ai/api/v1", Username = "[email protected]", Password = "password" }); base.PreInitialize(); } public override void Initialize() { IocManager.RegisterAssemblyByConvention(typeof(CarolModule).GetAssembly()); } } |
Como podemos perceber na definição de nosso modulomódulo, colocamos como dependência através do uso do atributo "DependsOn" a classe o módulo "TnfCarolModule" que fará a configuração de toda a infraestrutura do Carol para uso no assembly criado.Agora podemos fazer uso da estrutura do Carol no TNF
No método PreInitialize estamos configurando através da FluentAPI usando o método TnfCarol, informando as credenciais do serviço, ApplicationId, TenantId, BaseAddress, Username e Password.
Para definir sua estrutura no Carol é preciso fazer sua especificação na declaração da entidade. Neste exemplo vamos criar uma entidade chamada "President":
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using Newtonsoft.Json;
using Tnf.App.Carol.Repositories;
[JsonObject("president")]
public class PresidentEntity : CarolEntity
{
public string Name { get; set; }
public string ZipCode { get; set; }
public override object GetStagingMapping()
{
return new
{
name = "string",
zipCode = "string"
};
}
} |
Toda entidade do Carol deve herdar da classe CarolEntity fazendo a sobrescrita do método chamado GetStagingMapping, definindo assim a estrutura que o dado (nome e tipo do dado) que será persistido dentro do Carol.
No Carol as entidades entram em sua infraestrutura como Stagingse tornam registros de Staging em um primeiro momento. Após isso são criados modelos onde esses dados brutos (staging) serão mapeados para DataModels.
Um segundo passo seria a configuração dentro do serviço do Carol para uso de seu MDM (Master Data Management), criando regras de merge, normalização de dados, etc.
O uso do atributo JsonObject provindo do framework Json.NET usado para serialização de entidades descreve o nome da entidade no Carol. Caso a classe que a represente não possua esse atributo o , seu nome da classe será usado como referencia.
...
O pacote instalado Tnf.Provider.Carol prove alguns wrappers um repositório para utilização do Carol para operações de inserção, atualização, deleção e consulta de informações.
Essas funcionalidades estão disponíveis através do repositório CarolRepositoryBase<Entity>
chamado CarolRepositoryBase<Entity>.
Vamos criar um repositório para uso de nossa entidade chamado WhiteHouseRepositorycom a definição de sua interface:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using System.Collections.Generic; using System.Threading.Tasks; using Tnf.Domain.Repositories; using Tnf.Architecture.Dto.WhiteHouse; using Tnf.App.Dto.Response; using Tnf.App.Dto.Request; using Tnf.Architecture.Domain.WhiteHouse; namespace Tnf.Architecture.Domain.Interfaces.Repositories { public interface IWhiteHouseRepository : IRepository { Task<PagingDtoResponse<PresidentDto>> GetAll(GellAllPresidentsRequestDto Task<ListDto<PresidentDto>> GetAllPresidents(GetAllPresidentsDto request); Task<PresidentDto> GetByIdGetPresidentById(stringRequestDto<string> idrequestDto); Task<List<PresidentDto>> Task<List<string>> InsertAsyncInsertPresidentsAsync(List<PresidentDto>List<President> presidents, bool sync = false); TaskTask<President> UpdateAsyncUpdatePresidentsAsync(PresidentDtoPresident president); Task DeleteAsync Task<bool> DeletePresidentsAsync(string id); } } |
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using System.Collections.Generic; using System.Threading.Tasks; using Tnf.App.Carol.Repositories; using Tnf.Provider.Carol; using Tnf.Architecture.Domain.Interfaces.Repositories; using Tnf.Architecture.Data.Entities; using Tnf.AutoMapper; using Tnf.Architecture.Dto.WhiteHouse; using Tnf.App.Dto.Response; using Tnf.App.Dto.Request; using Tnf.Architecture.Domain.WhiteHouse; using System.Linq; namespace Tnf.Architecture.Data.Repositories { public class WhiteHouseRepository : CarolRepositoryBase<PresidentEntity>CarolRepositoryBase<PresidentPoco>, IWhiteHouseRepository { public WhiteHouseRepository(ICarolClient client) : base(client) { } { } public async TaskTask<bool> DeleteAsyncDeletePresidentsAsync(string id) => { return await DeleteAsync(id); } public async Task<PagingDtoResponse<PresidentDto>>Task<ListDto<PresidentDto>> GetAllGetAllPresidents(GellAllPresidentsRequestDtoGetAllPresidentsDto request) { { var response = new PagingDtoResponse<PresidentDto>ListDto<PresidentDto>(); var query = Client.Queries<PresidentEntity>Queries<PresidentPoco>().ProcessFilter() .Offset(request.Offset) .PageSize(request.PageSize) .SkipAndTakeByRequestDto(request) .OrderByRequestDto(request) .IndexType(Provider.Carol.Messages.ProcessFilter.IndexType.STAGING) .MustList((m) => m.TypeFilter() .MatchFilter(p => p.Name, request.Name) .TermFilter(p => p.Address.ZipCode.Number, request.ZipCode)); var resultData = await GetAllAsync(query); response.Count response.Total = resultData.CountTotalHits; response.TookItems = resultData.Hits.Took; response.TotalHitsMapTo<List<PresidentDto>>(); response.HasNext = resultData.TotalHits; resultData.Hits.ForEach((item) => response.Data.Add(new PresidentDto(item.Id, item.Name, item.ZipCode))); return response; } > ((request.Page - 1) * request.PageSize) + response.Items.Count(); return response; } public async Task<PresidentDto> GetByIdGetPresidentById(stringRequestDto<string> idrequestDto) { { var presidentData = await GetAsync(requestDto.GetId(id)); var president = new PresidentDto(presidentData.Id, presidentData.Name, presidentData.ZipCodeMapTo<PresidentDto>(); return president; } public async Task<List<PresidentDto>>Task<List<string>> InsertAsyncInsertPresidentsAsync(List<PresidentDto>List<President> presidents, bool sync = false) { var presidentEntities { var pocos = presidents.Select(s => new PresidentEntity() { Id = s.Id, Name = s.Name, ZipCode = s.ZipCode.Number }MapTo<List<PresidentPoco>>(); var result = await InsertAsync(pocos, sync); return result.Select(p => p.Id).ToList(); presidentEntities = await InsertAsync(presidentEntities, sync); return presidents; } } public async TaskTask<President> UpdateAsyncUpdatePresidentsAsync(PresidentDtoPresident president) { await UpdateAsync(new PresidentEntity() { Id { var poco = president.Id, Name = president.Name, ZipCode = president.ZipCode.Number }); MapTo<PresidentPoco>(); var result = await UpdateAsync(poco); return president; } } } |
Quando definimos o nosso nosso repositório recebemos como parâmetro uma interface chamada ICarolClient. Esse tipo é injetado via dependência representando o client de conexão com o Carol.
Através dele será possível criar queries consultas mais complexas ou acessar funcionalidades expostas dentro do provider . A herança do repositório do Carol já prove umas serie de métodos que facilitam a criação, atualização, deleção e consumo de serviço.
Para criar uma query consulta por exemplo note que o método GetAll de nosso repositório realiza a construção da query através do objeto ICarolClient usando a função: Client.Queries<PresidentEntity>().ProcessFilter().
Esse método retorna uma interface através de forma uma API fluente onde é possível construir a query consulta desejada. O método GetAllAsync do CarolRepositoryBase recebe o resultado dessa query criada retornando pelo Client.Queries<PresidentEntity>().ProcessFilter() retornando assim os registros que satisfazerem a sentença.
Essa API exposta e seu uso pode ser consultado através da documentação do Carol em http://docs.carol.ai/5-querying-data/
Note que no método InsertAsync InsertAsync do repositório do Carol recebe um parâmetro informando se a operação é síncrona ou assíncrona.: A diferença entre as operações é que a se da no modo como os dados são persistidos no Carol. A operação síncrona cria registro por registro na sequencia sequência e espera o seu processamento pela interface de MDM (Master Data Management) do Carol retornando após o dado passar por todo o processo.
Quando a operação é assíncrona os dados são inseridos em lote não esperando o seu processamento pelo MDM. Um processo posteriormente irá processar os registros pendentes no Carol.