Chamando Dibs em uma linha da tabela
-
22-08-2019 - |
Pergunta
O problema que tenho é esta:
Eu tenho uma tabela (apenas um exemplo) com os seguintes campos:
ID int
Value int
Eu tenho um método chamado IncreaseByFive () que faz o seguinte:
method IncreaseByFive(int ID)
{
int value = GetValueFromDB(ID);
value = value + 5;
SaveValueToDB(value, ID);
}
O que eu quero evitar é a seguinte situação:
- Um usuário chama o método e obtém o valor (atualmente 5)
- O usuário B chama o método e obtém o valor (atualmente 5)
- Um usuário aumenta o valor de 5 (agora 10)
- O usuário B aumenta o valor de 5 (agora 10)
- Um usuário salva o valor (10)
- O usuário B salva o valor (10)
Agora, o registro tem um valor de 10, quando deveria ter sido 15.
O que eu quero força é o seguinte:
- Um usuário chama o método e obtém o valor (atualmente 5)
- O usuário B chama o método, mas tem que esperar porque um já chamou. (Dibs!)
- Um usuário aumenta o valor (agora 10)
- O usuário B ainda está à espera
- Um usuário salva o valor (registro tem o valor de 10)
- O usuário B pode agora ler o valor (10)
- O usuário B aumenta o valor (15)
- O usuário B salva o valor
Agora, o registro tem um valor de 15, que é o resultado que eu estou procurando.
Eu já resolveu este problema no passado usando uma classe estática e colocar um bloqueio em um objeto estático criado dentro do construtor dessa classe, canalizando assim todo o trabalho através de um método estático, o que obriga as outras chamadas de esperar na fila . Receio, porém, que isso não é escalável.
Eu também acho que o mais alto nível de isolamento (serializável) para uma transação não irá fazer o truque, quer porque vai permitir a leitura no passo 2 do exemplo indesejado acima.
Eu suponho que outra solução seria criar minha própria mesa de bloqueio e gravar as fechaduras lá, mas que parece que não deve ser necessário.
Estou desenvolvendo esse projeto com C # (3.5) e SQL Server 2008.
O que a mente da colmeia acha?
Solução
Talvez eu seja mais underthinking isso, mas você não iria só embrulhar todo o bloco lógica ..
- valor lido
- valor escrita ??li>
em uma transação do banco de dados do rel="nofollow noreferrer"> nível adequado
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SNAPSHOT
| SERIALIZABLE
}
[ ; ]