Операторы LINQ для создания вложенного списка DynamicTableEntities по 100 блоков - PullRequest
0 голосов
/ 07 января 2020

Я пытаюсь создать пакеты из 100 записей, которые можно удалить из Azure Хранилище таблиц. Я нашел отличную статью об эффективном создании пакетов для удаления записей таблицы здесь: https://blog.bitscry.com/2019/03/25/efficiently-deleting-rows-from-azure-table-storage/

и следил за этим. Проблема, с которой я сталкиваюсь, отличается от примера, приведенного в этом сообщении, в том, что мои удаления будут иметь разные ключи раздела. так что вместо того, чтобы просто разбивать мои результаты на партии по 100 (как это происходит в примере), мне сначала нужно разбить их на группы одинаковых ключей разделения, а затем исследовать эти списки и дополнительно подразделить их, если число больше, чем 100 (так как Azure рекомендует только партии из 100 записей одновременно, и все они требуют одного и того же ключа раздела)

Позвольте мне сказать, что я УЖАСЕН с перечислимым LINQ и стилем без запроса, который описан в этот пост в блоге, так что я немного потерян. я написал небольшую работу, которая создает эти пакеты по идентификатору раздела, и код работает для их удаления, я просто не рассматриваю возможность удаления более 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());
 }

Я пытался сделать несколько операторов groupby в функции linq, подобной этой

// 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), тогда мой выбор ниже начинает go грушевидной формы. Объектом конечного результата является СПИСОК СПИСКОВ, который содержит DyanmicTableEntities и индекс

[0]
  [0][Entity]
  [1][Entity]
   ...
  [99][Entity]
[1]
  [0][Entity]
  [1][Entity]
   ... 

. Я надеюсь, что это имеет смысл, если нет, не стесняйтесь просить разъяснений.

Заранее спасибо.

РЕДАКТИРОВАТЬ ДЛЯ УТОЧНЕНИЯ:

Идея состоит в том, что я просто хочу сгруппировать по ключу PARTITION И взять только 100 строк перед созданием другой строки ЖЕ ключ разделения и добавление остальных строк

спасибо,

1 Ответ

0 голосов
/ 18 января 2020

Один полезный метод LINQ, который вы можете использовать: GroupBy (keySelector) . Это в основном делит вашу коллекцию на группы на основе селектора. Так что в вашем случае вы, вероятно, захотите сгруппировать по PartitionKey:

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

Когда вы выполните итерацию по этой коллекции, вы получите IGrouping . Наконец, чтобы получить правильную партию, вы можете использовать Skip (int count) и 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;
        }
    }
...