DynamoDB -如何使用ServiceStack.Aws实现乐观锁定



目前,我正在使用ServiceStack。与DynamoDB通信的Aws v5.9.0。我已经使用PutItem来创建和更新项目,而不会在并发处理的情况下预期数据丢失。

public class Customer
{
[HashKey]
public int CustomerId { get; set; }
[AutoIncrement]
public int SubId { get; set; }
public string CustomerType { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
...//and hundreds of fields here
}
public class CustomerDynamo
{
private readonly IPocoDynamo db;
//Constructor
public CustomerDynamo() 
{
var dynamoClient = new AmazonDynamoDBClient(_region);
var entityType = typeof(Customer);
var tableName = entityType.Name;
entityType.AddAttributes(new AliasAttribute(name: tableName));
db = new PocoDynamo(dynamoClient) { ConsistentRead = true }.RegisterTable(tableType: entityType);
}
public Customer Update(Customer customer)
{
customer.ModifiedDate = DateTime.UtcNow;
db.PutItem(customer);
return customer;
}
}

上面的Update方法在每个需要更新客户数据的服务/异步任务中被调用。参考这篇关于AWS的文章,我决定实现乐观锁定,以避免并发请求的问题。https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBContext.VersionSupport.html

假设VersionNumber将是乐观锁定的键。因此,我将VersionNumber添加到Customer模型中。

public class Customer
{
[HashKey]
public int CustomerId { get; set; }
[AutoIncrement]
public int SubId { get; set; }
public string CustomerType { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
...//and hundreds of fields here
[DynamoDBVersion]
public int? VersionNumber { get; set; }
}
  1. 结果是版本号没有更新,而它应该自动增加。我认为这只是因为putiitem将覆盖整个现有项。这是正确的吗?
  2. 我想我需要在Update方法中从putiitem更改为UpdateItem。问题是如何动态生成要与UpdateItem一起使用的表达式?

提前感谢您的帮助!

更新:

谢谢@mythz以获取有关DynamoDBVersion属性的有用信息。然后我试图删除DynamoDBVersion和使用PocoDynamo的UpdateExpression如下

public Customer Update(Customer customer)
{
customer.ModifiedDate = DateTime.UtcNow;
var expression = db.UpdateExpression<Customer>(customer.CustomerId).Set(() => customer);
expression.ExpressionAttributeNames = new Dictionary<string, string>() 
{ 
{ "#Version", "VersionNumber" } 
};
expression.ExpressionAttributeValues = new Dictionary<string, AttributeValue>() 
{
{ ":incr", new AttributeValue { N = "1" } },
{ ":zero", new AttributeValue { N = "0" } }
};
expression.UpdateExpression = "SET #Version = if_not_exists(#Version, :zero) + :incr";
if (customer.VersionNumber.HasValue)
{
expression.Condition(c => c.VersionNumber == customer.VersionNumber);
}
var success = db.UpdateItem(expression);
}

但是除了VersionNumber

之外,所有更改都不保存

[DynamoDBVersion]是一个AWS对象持久化模型属性,用于AWS的DynamoDBContext而不是PocoDynamo。例如,PocoDynamo使用的唯一[DynamoDB*]属性是[DynamoDBHashKey][DynamoDBRangeKey],所有其他[DynamoDB*]属性都用于AWS的对象持久化模型库。

需要时,您可以使用以下命令访问AWS的IAmazonDynamoDB:

var db = new PocoDynamo(awsDb);
var awsDb = db.DynamoDb;

这里是PocoDynamo的UpdateItem api的文档,可能是相关的。

最新更新