Introdução

Um conflito de concorrência de alterações em banco de dados ocorre quando dois usuários abrem para edição o mesmo registro, um deles salva uma modificação e então o outro ao salvar as suas modificações sobrescreve informações mais recentes.

Concorrência Otimista

O tratamento de concorrência otimista irá detectar quando um usuário tenta salvar um registro que já foi modificado por outro usuário. Neste momento, podemos tratar a exceção e pedir para o usuário recarregar o registro.

Preparando as Tabelas de Banco de Dados

O caminho mais fácil para detectar se um registro foi modificado antes de salvá-lo é criar um campo para indicar a versão atual do registro. Este campo será incluído nos filtros das queries de DELETE e UPDATE. Ou seja, se você abriu um registro com a versão “XXXX” você só poderá atualizar se a versão atual daquele registro no banco de dados for “XXXX”.

A sua classe de mapeamento deve possuir um campo para versionamento marcado com o atributo Timestamp. Este campo será incluído nos filtros dos queries de DELETE e UPDATE.

public class Aluno
{
    public virtual int CodAluno { get; set; }
    public virtual string CPF { get; set; }
    public virtual DateTime DataIngresso { get; set; }

    [Timestamp]
    public virtual byte[] Versao { get; set; }
}

Um detalhe importante é que ao exibir o registro para o usuário você deverá armazenar o valor do campo “Versao”, pois precisará passar este campo ao tentar salvar as alterações. Em MVC você pode criar um campo Hidden assim:

@Html.HiddenFor(model => model.Versao)

Outro ponto importante é tratar a exceção lançada ao tentar alterar um registro já modificado. O tipo da exceção é o DbUpdateConcurrencyException. Você pode tratar essa exceção encapsulando a chamada ao SaveChanges() dentro de um try..catch como esse:

public int SalvarModificacoes(Dictionary errosValidacao)
{
    int quantidadeModificacoes = 0;

    try
    {
        quantidadeModificacoes = contexto.SaveChanges();
    }
    catch (DbUpdateConcurrencyException ex)
    {
        errosValidacao.Add("", "O registro foi modificado por outro usuário");
    }

    return quantidadeModificacoes;
}