И в EF6, и в EF-core, когато работите със Sql Server, трябва да използвате това съпоставяне:
modelBuilder.Entity<Product>()
.Property(t => t.RowVersion)
.IsRowVersion(); // Not: IsConcurrencyToken
IsConcurrencyToken конфигурира свойство като маркер за едновременност, но (когато го използвате за byte[]
свойство)
- типът данни е
varbinary(max)
- стойността му винаги е
null
ако не го инициализирате - стойността му не се увеличава автоматично при актуализиране на запис.
IsRowVersion от друга страна,
- има тип данни
rowversion
(в Sql сървър илиtimestamp
в по-ранни версии), така че - стойността му никога не е нула, и
- стойността му винаги се увеличава автоматично, когато записът се актуализира.
- и автоматично конфигурира свойството да бъде оптимистичен токен за паралелност.
Сега, когато актуализирате Car
ще видите две изявления за актуализиране:
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 ...
Първият израз не актуализира нищо, но увеличава версията на реда и ще изведе изключение за едновременност, ако версията на реда е променена между тях.
[System.ComponentModel.DataAnnotations.Schema.Timestamp]
атрибутът е анотациите към данните, еквивалентни на IsRowVersion()
:
[Timestamp]
public byte[] RowVersion { get; set; }