LINQ 语句以 100 个块为单位执行 DynamicTableEntities 的嵌套列表

LINQ statements to do a nested list of DynamicTableEntities in chunks of 100

我正在尝试创建我可以从 Azure Table 存储中删除的 100 条记录的批次。我在此处找到了一篇关于高效创建批处理以删除 table 记录的好文章:https://blog.bitscry.com/2019/03/25/efficiently-deleting-rows-from-azure-table-storage/

并一直关注着这一点。我面临的问题与此博客中的示例不同 post 是我的删除将具有不同的分区键。因此,与其简单地将我的结果分成 100 个批次(如示例中那样),我首先需要将它们分成类似分区键的组,然后检查这些列表,如果计数大于则进一步细分它们100(因为 Azure 建议一次只分批处理 100 条记录,并且它们都需要相同的分区键)

让我说我对可枚举的 LINQ 和本博客中描述的非查询样式很糟糕 post 所以我有点迷茫。我已经写了一个小的解决方法,确实通过分区 ID 创建这些批次,并且代码可以删除它们,我只是没有处理可能有超过 100 行要根据分区键删除的可能性。因此,下面的代码仅用作示例,向您展示我是如何通过分区键拆分更新的。

List<string> partitionKeys = toDeleteEntities.Select(x => x.PartitionKey).Distinct().ToList();

List<List<DynamicTableEntity>> chunks = new List<List<DynamicTableEntity>>();

for (int i = 0; i < partitionKeys.Count; ++i)
 {
  var count = toDeleteEntities.Where(x => x.PartitionKey == partitionKeys[i]).Count();
          //still need to figure how to split by groups of 100.
         chunks.Add(toDeleteEntities.Distinct().Where(x=>x.PartitionKey == partitionKeys[i]).ToList());
 }

我曾尝试在类似于此的 linq 函数中执行多个 groupby 语句

// Split into chunks of 100 for batching
        List<List<TableEntity>> rowsChunked = tableQueryResult.Result.Select((x, index) => new { Index = index, Value = x })
            .Where(x => x.Value != null)
            .GroupBy(x => x.Index / 100)
            .Select(x => x.Select(v => v.Value).ToList())
            .ToList();

但是一旦我将第二组参数添加到分组依据(例如:x=>x.PartitionKey)然后我下面的 select 开始变成梨形。最终结果对象是包含 DyanmicTableEntities 和索引

的 LISTS 的 LIST
[0]
  [0][Entity]
  [1][Entity]
   ...
  [99][Entity]
[1]
  [0][Entity]
  [1][Entity]
   ... 

我希望这是有道理的,如果没有,请随时要求澄清。

提前致谢。

编辑澄清:

我的想法很简单,我想按分区键分组,并且在创建另一行相同分区键并添加其余行之前只取 100 行

谢谢,

您可以使用的一种有用的 LINQ 方法是 GroupBy(keySelector)。它基本上根据选择器将 collection 分成几组。所以在你的情况下,你可能想按 PartitionKey:

var partitionGroups = toDeleteEntities.GroupBy(d => d.PartitionKey);

当你遍历这个 collection 时,你会得到一个 IGrouping. Finally, to get the correct batch, you can use Skip(int count) and Take(int count)

    foreach (var  partitionGroup  in  partitionGroups)
    {
        var  partitionKey = partitionGroup.Key;
        int  startPosition = 0;
        int  count = partitionGroup.Count();

        while(count > 0)
        {
            int  batchSize = count % maxBatchSize > 0 ? count % maxBatchSize : maxBatchSize;

            var  partitionBatch = partitionGroup.Skip(startPosition).Take(batchSize);
            // process your batches here
            chunks.Add(new  List<DynamicTableEntry>(partitionBatch));

            startPosition += batchSize;
            count = count - batchSize;
        }
    }