Tanto no EF6 quanto no EF-core, ao trabalhar com Sql Server, você deve usar este mapeamento:
modelBuilder.Entity<Product>()
.Property(t => t.RowVersion)
.IsRowVersion(); // Not: IsConcurrencyToken
IsConcurrencyToken configura uma propriedade como token de simultaneidade, mas (ao usá-la para um
byte[]
propriedade) - o tipo de dados é
varbinary(max)
- seu valor é sempre
null
se você não inicializar - seu valor não é incrementado automaticamente quando um registro é atualizado.
IsRowVersion por outro lado,
- tem o tipo de dados
rowversion
(no Sql Server, outimestamp
em versões anteriores), então - seu valor nunca é nulo e
- seu valor é sempre incrementado automaticamente quando um registro é atualizado.
- e configura automaticamente a propriedade para ser um token de simultaneidade otimista.
Agora, quando você atualiza um
Car
você verá duas instruções de atualização:DECLARE @p int
UPDATE [dbo].[Product]
SET @p = 0
WHERE (([Id] = @0) AND ([Rowversion] = @1))
SELECT [Rowversion]
FROM [dbo].[Product]
WHERE @@ROWCOUNT > 0 AND [Id] = @0
UPDATE [dbo].[Car]
SET ...
A primeira instrução não atualiza nada, mas incrementa a versão de linha e lançará uma exceção de simultaneidade se a versão de linha tiver sido alterada no meio.
O
[System.ComponentModel.DataAnnotations.Schema.Timestamp]
atributo é o equivalente das anotações de dados de IsRowVersion()
:[Timestamp]
public byte[] RowVersion { get; set; }