乐观并发:IsConcurrencyToken 和 RowVersion [英] Optimistic concurrency: IsConcurrencyToken and RowVersion
问题描述
我正在创建将在我的应用程序中使用的默认并发策略.
我决定采用乐观的策略.
我的所有实体都映射为 Table per Type (TPT)
(使用继承).很快我就了解到,在 Entity Framework 上使用带有继承的 RowVersion 类型的列时会出现问题:
产品Id INT 身份主键行版本 ROWVERSION汽车(继承产品记录)颜色 TYNIINT 不为空,另一个属性....
如果我更新 Car
表的记录,Product
表中的 RowVersion 列将不会更新.
我打算在 Product
中使用 datetime2 (7)
类型的列,并在继承该表的表的任何记录被修改时手动更新它.>
我想我正在重新发明轮子.
在实体框架中使用 Table per Type (TPT)
时,是否有另一种方法可以将乐观并发策略与 ROWVERSION
一起使用?
编辑
我的映射:
class 产品{int ID { 获取;放;}字符串名称 { 获取;放;}字节 [] 行版本 { 获取;放;}}类别 汽车 : 产品{int 颜色 { 得到;放;}}
CodeFirst 约定.
只有 Product
实体上的 RowVersion 属性有自定义定义:
modelBuilder.Entity().Property(t => t.RowVersion).IsConcurrencyToken();
EF6 和 EF-core 中,使用 Sql Server 时,必须使用此映射:
modelBuilder.Entity().Property(t => t.RowVersion).IsRowVersion();//不是:IsConcurrencyToken
IsConcurrencyToken 确实将属性配置为并发令牌,但是(当将其用于 byte[]
属性时)
- 数据类型为
varbinary(max)
- 如果你不初始化它,它的值总是
null
- 当记录更新时,它的值不会自动增加.
IsRowVersion 另一方面,
- 具有数据类型
rowversion
(在 SQL Server 中,或在早期版本中为timestamp
),所以 - 它的值永远不会为空,并且
- 当记录更新时,它的值总是自动递增.
- 并且它会自动将该属性配置为乐观并发令牌.
现在,当您更新 Car
时,您将看到两个更新语句:
DECLARE @p int更新 [dbo].[产品]设置@p = 0WHERE (([Id] = @0) AND ([Rowversion] = @1))选择 [行版本]来自 [dbo].[产品]哪里@@ROWCOUNT >0 AND [Id] = @0更新 [dbo].[汽车]放 ...
第一条语句没有更新任何内容,但它增加了 rowversion,如果在这之间更改了 rowversion,它将抛出并发异常.
[System.ComponentModel.DataAnnotations.Schema.Timestamp]
属性是等效于 IsRowVersion()
的数据注释:
[时间戳]公共字节[] RowVersion { 获取;放;}
I'm creating the default concurrency strategy that I will use in my application.
I decided for an optimistic strategy.
All of my entities are mapped as Table per Type (TPT)
(using inheritance). I soon learned that there is a problem when using columns of type RowVersion with inheritance on Entity Framework:
Product
Id INT IDENTITY PRIMARY KEY
RowVersion ROWVERSION
Car (inherits Product records)
Color TYNIINT NOT NULL,
AnotherProperty....
If I update a record of the Car
table the RowVersion column from Product
table will not be updated.
I plan to use a column of type datetime2 (7)
in Product
and update it manually if any records of the tables that inherit this table are modified.
I think I'm reinventing the wheel.
Is there another way to use the optimistic concurrency strategy with ROWVERSION
when using Table per Type (TPT)
in Entity Framework?
Edit
My mapping:
class Product
{
int Id { get; set; }
string Name { get; set; }
byte[] RowVersion { get; set; }
}
class Car : Product
{
int Color { get; set; }
}
CodeFirst conventions.
Only the RowVersion property on Product
entity has custom definitions:
modelBuilder.Entity<Product>()
.Property(t => t.RowVersion)
.IsConcurrencyToken();
Both in EF6 and EF-core, when working with Sql Server, you have to use this mapping:
modelBuilder.Entity<Product>()
.Property(t => t.RowVersion)
.IsRowVersion(); // Not: IsConcurrencyToken
IsConcurrencyToken does configure a property as concurrency token, but (when using it for a byte[]
property)
- the data type is
varbinary(max)
- its value is always
null
if you don't initialize it - its value is not auto-incremented when a record is updated.
IsRowVersion on the other hand,
- has datatype
rowversion
(in Sql Server, ortimestamp
in earlier versions), so - its value is never null, and
- its value is always auto-incremented when a record is updated.
- and it automatically configures the property to be an optimistic concurrency token.
Now when you update a Car
you'll see two update statements:
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 ...
The first statement doesn't update anything, but it increments the rowversion, and it will throw a concurrency exception if the rowversion was changed in-between.
The [System.ComponentModel.DataAnnotations.Schema.Timestamp]
attribute is the data annotations equivalent of IsRowVersion()
:
[Timestamp]
public byte[] RowVersion { get; set; }
这篇关于乐观并发:IsConcurrencyToken 和 RowVersion的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!