我正在创建将在应用程序中使用的默认并发策略。
我决定采取乐观的策略。
我所有的实体都映射为Table per Type (TPT)
(使用继承)。我很快了解到,在 Entity Framework 上使用具有继承性的RowVersion类型的列时会出现问题:
Product
Id INT IDENTITY PRIMARY KEY
RowVersion ROWVERSION
Car (inherits Product records)
Color TYNIINT NOT NULL,
AnotherProperty....
如果我更新
Car
表的记录,那么Product
表中的RowVersion列将不会更新。我计划在
datetime2 (7)
中使用Product
类型的列,并在继承该表的表的任何记录被修改后手动对其进行更新。我想我正在重新发明轮子。
在Entity Framework中使用
ROWVERSION
时,还有另一种方法可以对Table per Type (TPT)
使用乐观并发策略吗?编辑
我的映射:
class Product
{
int Id { get; set; }
string Name { get; set; }
byte[] RowVersion { get; set; }
}
class Car : Product
{
int Color { get; set; }
}
CodeFirst 约定。
只有
Product
实体上的RowVersion属性具有自定义定义:modelBuilder.Entity<Product>()
.Property(t => t.RowVersion)
.IsConcurrencyToken();
最佳答案
在EF6和EF-core中,使用Sql Server时,都必须使用此映射:
modelBuilder.Entity<Product>()
.Property(t => t.RowVersion)
.IsRowVersion(); // Not: IsConcurrencyToken
IsConcurrencyToken 确实将属性配置为并发 token ,但是(将其用于
byte[]
属性时)varbinary(max)
null
另一方面, IsRowVersion ,
rowversion
(在Sql Server中,或在较早版本中为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; }