Skip to content

Optimistic concurrency

shuxin edited this page Nov 10, 2023 · 3 revisions

乐观并发

Chloe.ORM 可以给实体设置行版本号,以支持乐观并发更新/删除,具体操作如下:

设置属性为行版本:

特性方式配置:

[TableAttribute("Person")]
public class Person
{
    [Column(IsPrimaryKey = true)]
    public int Id { get; set; }
    
    //...    

    //设置 RowVersion 字段为行版本
    [Column(IsRowVersion = true)]
    public int RowVersion { get; set; }

    //...  
}

Fluent mapping 方式配置:

public class PersonMap : EntityMapBase<Person>
{
    public PersonMap()
    {
        //...

        this.Property(a => a.RowVersion).IsRowVersion();

        //...
    }
}

更新:

//实体更新
Person person = dbContext.Query<Person>().First(a => a.Id == 1);
dbContext.TrackEntity(person);//在上下文中跟踪实体
person.Name = person.Name + "1";

Console.WriteLine(person.RowVersion);  //此时输出版本号 1

//执行更新时会自动加上 [Person].[RowVersion] = @P_2 作为更新条件,并更新 RowVersion 字段
dbContext.Update(person);
/*
 * Input String @P_0 = 'Chloe1';
   Input Int32 @P_1 = 2;
   Input Int32 @P_2 = 1;
   UPDATE [Person] SET [Name]=@P_0,[RowVersion]=@P_1 WHERE ([Person].[Id] = @P_2 AND [Person].[RowVersion] = @P_2)
 */

Console.WriteLine(person.RowVersion);  //此时输出为新的版本号 2

删除:

//实体删除
Person person = dbContext.Query<Person>().First();

//执行删除时会自动加上 [Person].[RowVersion] = @P_1 作为删除条件
dbContext.Delete(person);
/*
 * Input Int32 @P_0 = 1;
   Input Int32 @P_1 = 2;
   DELETE FROM [Person] WHERE ([Person].[Id] = @P_0 AND [Person].[RowVersion] = @P_1)
 */

:如果调用 Update/Delete 方法后受影响的行数为 0,会引发 OptimisticConcurrencyException 异常。

目前 Chloe.ORM 对于行版本属性只支持 int、long 类型,如果是 SqlServer 还支持 Byte[] 类型(对应 SqlServer 的 timestamp 类型)。