OptimisticConcurrencyException não funciona na estrutura de entidades em determinadas situações
UPDATE (21-12-2010): reescreveu completamente essa pergunta com base nos testes que eu venho fazendo. Além disso, essa costumava ser uma pergunta específica do POCO, mas acontece que minha pergunta não é necessariamente específica do POCO.
Estou usando o Entity Framework e tenho uma coluna de carimbo de data e hora na minha tabela de banco de dados que deve ser usada para rastrear alterações para simultaneidade otimista. Eu configurei o modo de simultaneidade para esta propriedade no Designer de entidade como "Fixo" e estou obtendo resultados inconsistentes. Aqui estão alguns cenários simplificados que demonstram que a verificação de simultaneidade funciona em um cenário, mas não em outro.
Lança com êxito OptimisticConcurrencyException:
Se eu anexar uma entidade desconectada, o SaveChanges lançará uma OptimisticConcurrencyException se houver um conflito de carimbo de data / hora:
[HttpPost]
public ActionResult Index(Person person) {
_context.People.Attach(person);
var state = _context.ObjectStateManager.GetObjectStateEntry(person);
state.ChangeState(System.Data.EntityState.Modified);
_context.SaveChanges();
return RedirectToAction("Index");
}
Não lança OptimisticConcurrencyException:
Por outro lado, se eu recuperar uma nova cópia da minha entidade do banco de dados e fizer uma atualização parcial em alguns campos e depois chamar SaveChanges (), mesmo que haja um conflito de carimbo de data / hora, não recebo uma OptimisticConcurrencyException :
[HttpPost]
public ActionResult Index(Person person) {
var currentPerson = _context.People.Where(x => x.Id == person.Id).First();
currentPerson.Name = person.Name;
// currentPerson.VerColm == [0,0,0,0,0,0,15,167]
// person.VerColm == [0,0,0,0,0,0,15,166]
currentPerson.VerColm = person.VerColm;
// in POCO, currentPerson.VerColm == [0,0,0,0,0,0,15,166]
// in non-POCO, currentPerson.VerColm doesn't change and is still [0,0,0,0,0,0,15,167]
_context.SaveChanges();
return RedirectToAction("Index");
}
Com base no SQL Profiler, parece que o Entity Framework está ignorando o novo VerColm (que é a propriedade timestamp) e, em vez disso, está usando o VerColm originalmente carregado. Por isso, nunca lançará uma OptimisticConcurrencyException.
ATUALIZAÇÃO: Adicionando informações adicionais por solicitação de Jan:
Observe que eu também adicionei comentários ao código acima para coincidir com o que vejo na minha ação do controlador enquanto trabalhava neste exemplo.
Este é o valor do VerColm no meu DataBase antes da atualização: 0x0000000000000FA7
Aqui está o que o SQL Profiler mostra ao fazer a atualização:
exec sp_executesql N'update [dbo].[People]
set [Name] = @0
where (([Id] = @1) and ([VerColm] = @2))
select [VerColm]
from [dbo].[People]
where @@ROWCOUNT > 0 and [Id] = @1',N'@0 nvarchar(50),@1 int,@2 binary(8)',@0=N'hello',@1=1,@2=0x0000000000000FA7
Observe que @ 2 deveria ter sido 0x0000000000000FA6, mas é 0x0000000000000FA7
Aqui está o VerColm no meu DataBase após a atualização: 0x0000000000000FA8
Alguém sabe como posso solucionar esse problema? Gostaria que o Entity Framework gerasse uma exceção quando atualizasse uma entidade existente e houvesse um conflito de carimbo de data / hora.
obrigado