【问题标题】:Azure Storage and Conditional Replace/MergeAzure 存储和条件替换/合并
【发布时间】:2014-03-16 04:33:49
【问题描述】:

在 Azure 表存储的批量保存操作中,是否有一种有效的方法来替换已存在的实体上的某些属性;但更新新实体的所有属性?

这是我正在谈论的场景。

我有一个名为 Order 的实体

public class Order : TableEntity
{
    public Order(String department, string orderId)
    {
        this.PartitionKey = department;
        this.RowKey = orderId;
    }

    public DateTime CreatedOn {get; set;}
    public String CreatedBy {get; set;}

    public DateTime UpdatedOn {get; set;}
    public String UpdatedBy {get; set;}

    //Class contains other properties which could add up to 1MB
}

场景

  1. Azure 表存储具有使用 RowKeys [0..100] 的订单实体
  2. 我的 API 收到了一个带有 RowKeys [50..150] 的订单的 upsert 请求。
  3. 在单个批量事务中,我需要更新订单 [50-100] 的某些属性并在 azure 上创建新的订单实体 [101-150]。
  4. 注意: 在现有订单 [50..100] 上,除 CreatedOn、CreatedBy、PartitionKey 和 RowKey 之外的所有属性都需要更新。

我可以一步完成而不从表格存储中读取内容吗?

这是一种方法(非常粗略的伪代码)

function Upsert(Dictionary<String, Order> ordersInput)
{
    //1. Read existing ordersInput from database
    var existingOrders = Retrieve(ordersInput.Values);

    //2. Update 'ordersInput' with existing data
    foreach(var existingOrder in existingOrders)
    {
        if(ordersInput.ContainsKey(existingOrder.RowKey)
        {
            ordersInput[existingOrder.RowKey].CreatedOn = existingOrder.CreatedOn;
            ordersInput[existingOrder.RowKey].CreatedBy = existingOrder.CreatedBy;
        }
    }

    //Save all merged orders to Azure
    SaveToAzure(existingOrders);
}

我对上述方法的问题是每个订单实体的大小为 1 MB,并且读取所有实体会使 API 保存操作陷入困境。

有没有更有效的方法来完全在 azure 上执行条件合并?

我也在考虑通过以下方式进行批量插入

  1. 对所有订单进行批量插入
  2. 如果上一步失败并显示“指定的实体已经存在”,则创建两个新批次(一个具有现有行键,另一个具有新行键)并单独处理每个批次李>

(上面的方法听起来很hacky,我认为它可能会导致一堆并发问题)

【问题讨论】:

  • 你解决过这个问题吗?
  • 我使用了查询投影和插入合并的组合

标签: c# azure insert-update upsert azure-table-storage


【解决方案1】:

Azure 表存储通过 InsertOrReplaceInsertOrMerge 函数原生支持 Upsert 操作。 InsertOrReplace 将用新实体完全替换一个实体,如果它存在,否则它将创建一个新实体。 InsertOrMerge 将更改存在于新实体中的现有实体的属性,如果存在具有相同 PartitionKey/RowKey 的实体,否则它将创建一个新实体。

更新

这是另一种方法。您可以做的几件事:

  1. 查询投影:查询投影允许您仅获取实体的某些属性。因此,当您获取现有实体时,您只获取PartitionKeyRowKey,以便您可以确定实体是否已经存在。这将大大减少响应负载。
  2. 可空字段:由于您不想更新现有实体的 CreatedOnCreatedBy 字段,因此您需要使它们可空,尤其是 CreatedOn

基于此,您将首先获取现有实体。检索操作只会返回PartitionKeyRowKey(使用查询投影技术)。然后您将遍历ordersInput 并查看该实体是否存在。如果实体存在,则将CreatedOnCreatedBy 设置为null 并将该实体标记为Merged。如果实体不存在,您将设置所有属性并将该实体标记为Inserted。然后你将这个批处理请求发送到表服务。

【讨论】:

  • 我确实探索了 InsertOrMerge 操作,但它不适用于我提到的场景。如果实体已经在 Azure 上,是否有办法告诉 InsertOrMerge 跳过更新特定属性(例如,如果实体已经在 Azure 上,则不应覆盖 Created By Fields,即使在传递新值时也是如此)
猜你喜欢
  • 2022-01-22
  • 2016-12-15
  • 2021-07-21
  • 2014-03-29
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
相关资源
最近更新 更多