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

questionAnswers(4)

yourAnswerToTheQuestion