segunda-feira, 1 de junho de 2009

Controle de concorrência com Linq to Sql

Este artigo discutirá como o Linq to Sql suporta o tratamento a concorrência otimista.

Suporte do Linq to Sql
O L2S e o DataContext foi feito para suportar o controle de concorrência otimista, assim as alterações só são bem sucedidas se o estado do DB não mudou desde que recuperados os dados inicialmente.

Antes de nos aprofundarmos em L2SQL vamos aos conceitos de concorrência pessimista e otimista.

Concorrência Pessimista
Este tipo de tratamento de concorrência bloqueava os registros no Banco de Dados enquanto as alterações eram realizadas, evitando que outros usuários fizessem alterações ao mesmo tempo.

Este tipo de solução era bastante comum em sistemas “Windows Applications” pequenos. O que é inviável para sistemas com uma grande escala de usuários, ou “disconnected environment” como objetos guardados numa sessão Asp.Net.

Concorrência Otimista
Este modelo, permite que qualquer usuário faça alterações nas suas cópias de dados. Entretanto, quando estes valores forem salvos, primeiro deverá ser verificado se os valores modificados possuem como valores antigos os mesmos presentes no Banco de Dados. Se houver um conflito, o sistema deverá saber como se comportar.

Para melhor compreensão, este código Sql mostra como esta comparação é feita e como o conflito é identificado:

UPDATE dbo.Book
SET Title = @NewTitle,
Subject = @NewSubject,
Publisher = @NewPublisher,
PubDate = @NewPubDate,
Price = @NewPrice,
PageCount = @NewPageCount,
Isbn = @NewIsbn,
WHERE ID = @ID AND Title = @OldTitle AND
Subject = @OldSubject AND
Publisher = @OldPublisher AND
PubDate = @PubDate AND
Price = @Price AND
PageCount = @PageCount AND
Isbn = @OldIsbn AND
RETURN @@RowCount

Os objectos em memória guardam o valor original (o valor obtido da base de dados) e o valor actual (novo valor atribuído pelo utilizador). Como já terá percebido, um conflito ocorre quando o valor original do objecto não corresponde ao valor presente na base de dados, ou seja, na cláusula where vai um parâmetro onde o seu valor não corresponde ao valor presente na base de dados.

Solução para Optimistic concurrency
Lembrando apenas que para uma “Optimistic concurrency” temos 3 formas de resolver e elas serão abordadas usando Linq to Sql:

  1. Retém as alterações feitas inicialmente (Já persistidas no BD);
  2. Conserva a ultima alteração;
  3. Faz um merge dos valores;

Suporte Linq to Sql a solução para Optimistic concurrency
Precisamos antes de mais nada saber quais são os conflitos e informar ao Linq to Sql (DataContext) como resolver.

O DataContext nos permite descobrir não somente os objetos que estão em conflito, como as propriedades que são diferentes entre o valor original, o valor alterado, e
o valor atual do banco de dados.

  • UpdateCheck: Essa propriedade utilizada no mapeamento das entidades Linq para as colunas do DB, diz ao L2Sql como o mesmo utilizará esta coluna no procesamento da concorrência otimista (opções: Always (default), Never, WhenChanged).
    Esta propriedade determina a geração daquele Sql descrito lá em cima, portanto use com moderação para não degradar a performance (Considere outras formas como uso de RowVersion ou TimeStamp);
  • ConflictMode: Pode ser usado junto com o SubmitChanges. Permite-nos dizer como os conflitos deverão ser notificados quando detectado;
    • ContinueOnConflict: As alterações possíveis são realizadas e os conflitos são colocados numa collection e retornados ao fim do processo;
    • FailOnFirstConflict: Atualizações param imediatamente após a primeira ocorrência de conflito;

Db.SubmitChanges(ConflictMode.ContinueOnConflict);

  • RefreshMode: Permite-nos definir como o aplicativo deverá se comportar (tratar) ao encontrar um conflito (Optimistic concurrency). Manter valores originais, valores atuais do BD ou novos valores.
    • KeepChanges: Mantém os correntes valores que foram alterados, mas atualiza os outros valores com os correntes no banco de dados (Foco nas alterações e na ordem de ultima alteração é persistida);
    • KeepCurrentValues: Troca os valores originais pelos obtidos da base de dados. Valores atuais não são modificados;
    • OverWriteCurrentValues: Sobrescreve suas alterações com os valores presentes no banco de dados;

Até a próxima!!!

0 comentários:

Postar um comentário