Skip to content

Utilização do Identity Map Pattern para solicitar a busca do registro somente uma única fez durante um processamento

Notifications You must be signed in to change notification settings

martineli17/patterns-identity-map

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Identity Map Pattern

Contexto

O Identity Map é um pattern que visa trabalhar somente com uma única versão de um registro, tendo como objetivo de não gerar conflitos durante o fluxo de um processamento.

O seu conceito consiste em:

  • A primeira solicitação de busca por um registro irá acessar diretamente a fonte de dados e salvar a sua versão em memória.
  • As solicitações posteriores, durante o processamento daquele fluxo, irão acessar o registro que está em memória pela primeira solicitação feita.

Um exemplo de utilização desse pattern é implementá-lo na camada de Data/Repository da sua aplicação.

Com isso, quando for solicitado a busca de um registro (seja qual for a fonte de dados), a primeira solicitação irá pesquisar diretamente na origem de dados (um Banco de Dados ou um Cache, por exemplo). Enquanto isso, as demais solicitações daquele fluxo irão utilizar deste registro já retornado pela primeira solicitação.

Realizando essa implementação na camada de Data, é observado alguns benefícios, como:

  • O acesso ao banco de dados irá diminuir.
  • Não necessariamente precisamos repassar o objeto como parâmetro durante todo o fluxo do processamento, pois pode ser utilizado a interface de acesso a dados normalmente visto que a busca no banco de dados irá ocorrer uma única vez.

    Com isso, a necessidade de parâmetros tende a diminuir (tornando os métodos mais independentes) e os registros podem ser solicitados em qualquer ponto do processamento, sem aumentar as idas na fonte de dados.

  • Não será possível, no mesmo fluxo de processamento, trabalhar com mais de uma versão para o mesmo registro.

Exemplo de utilização

Neste exemplo, foi criado apenas 3 camadas:

  • Domain
  • Data
  • Apresentação

Na camada de Data, é encontrado a implementação do Context do EF e o Repositories. Mas, além disso, foi implementado a utilização do Identity Map.

A implementação consiste no seguinte fluxo:

  1. É necessário a criação de uma chave única para identificar o registro no Identity Map. O padrão utilizado foi o nome da entidade, o nome do método de busca e algum parâmetro. Arquivo
      public async Task<IEnumerable<Client>> GetByNameAsync(string name, CancellationToken cancellationToken)
        {
            var key = $"{nameof(Client)}_{nameof(GetByNameAsync)}_{name}";
            return await _identityMap.ExecuteAsync(key, () => _databaseContext.Client.Where(x => x.Name.ToLower().Contains(name)).ToListAsync(cancellationToken));
        }
    
  2. Ao solicitar o o registro através do Identity Map, é verificado se a chave informada existe. Se existir, retorna o registro que está em memória. Caso não exista, realiza a busca normalmente e salva o retorno com a chave informada. Arquivo
    public async Task<TReturn> ExecuteAsync<TReturn>(string key, Func<Task<TReturn>> func)
        {
            if (_identityMap.HasObject(key))
            {
                _logger.LogInformation("Getting the data {0} from Identity Map", key);
                return _identityMap.GetObjet<TReturn>(key);
            }
    
            var result = await func();
            _logger.LogInformation("Getting the data {0} from DataBase", key);
            _identityMap.MapObject(key, result);
    
            return result;
        }
    
  3. E a implementação do Identity Map, fica da seguinte maneira: Arquivo
    public class IdentityMapManager : IIdentityMapManager
    {
        private readonly Dictionary<string, object> _objectsMapped;
    
        public IdentityMapManager()
        {
            _objectsMapped = new();
        }
    
        public TReturn GetObjet<TReturn>(string key)
        {
            return (TReturn)_objectsMapped[key];
        }
    
        public void MapObject(string key, object value)
        {
            if (!_objectsMapped.ContainsKey(key))
                _objectsMapped[key] = value;
        }
    
        public bool HasObject(string key)
        {
            return _objectsMapped.ContainsKey(key);
        }
    }
    
  4. No final, quem solicitar estes dados não precisa se preocupar em estar acessando o banco de dados em cada uma das chamadas (código somente para testes):
    [HttpGet]
        public async Task<IActionResult> GetAll(CancellationToken cancellationToken)
        {
            await _clientRepository.GetAllAsync(cancellationToken);
            var result = await _clientRepository.GetAllAsync(cancellationToken);
    
            return Ok(result);
        }
    

About

Utilização do Identity Map Pattern para solicitar a busca do registro somente uma única fez durante um processamento

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages