删除所有Azure表记录

Cmd*_*len 15 c# azure azure-storage azure-table-storage

我有一个Azure存储表,它有3k +记录.

删除表中所有行的最有效方法是什么?

Gau*_*tri 20

对于3000条记录,最简单的方法是删除表格.但请注意,当您删除表时,它当时不会被删除,而是被放入某种队列中删除,并且实际上会在一段时间后删除.此时间取决于系统上的负载+表中实体的数量.在此期间,您将无法重新创建此表或使用此表.

如果您继续使用该表很重要,则唯一的其他选项是删除实体.要获得更快的删除,您可以查看使用删除实体Entity Batch Transactions.但是要删除实体,您需要先获取实体.您可以通过只取加快抓取过程PartitionKeyRowKey实体的属性,而不是获取,因为只有这两个属性都需要删除一个实体的所有属性.


Jon*_* M. 9

对于后来发现这一点的人来说,接受的答案“刚刚删除了表”的问题是,虽然它在存储模拟器中运行良好,但在生产中会随机失败。如果您的应用程序/服务需要定期重新生成表,那么您会发现由于冲突或删除仍在进行中而导致失败。

相反,我发现最快且最防错 EF 友好的方法是删除分段查询中的所有行。下面是我正在使用的一个简单的插入示例。传入您的客户端、表名称和实现 ITableEntity 的类型。

private async Task DeleteAllRows<T>(string table, CloudTableClient client) where T: ITableEntity, new()
    {
        // query all rows
        CloudTable tableref = client.GetTableReference(table);           
        var query = new TableQuery<T>();
        TableContinuationToken token = null;
                                         
        do
        {
            var result = await tableref.ExecuteQuerySegmentedAsync(query, token);  
            foreach (var row in result)
            {
                var op = TableOperation.Delete(row);
                tableref.ExecuteAsync(op);
            }
            token = result.ContinuationToken;
        } while (token != null);  
        
    }
Run Code Online (Sandbox Code Playgroud)

用法示例:

table = client.GetTableReference("TodayPerformanceSnapshot");
created = await table.CreateIfNotExistsAsync();

if(!created)
{ 
    // not created, table already existed, delete all content
   await DeleteAllRows<TodayPerformanceContainer>("TodayPerformanceSnapshot", client);
   log.Information("Azure Table:{Table} Purged", table);
}
Run Code Online (Sandbox Code Playgroud)

批处理方法需要花费更多的精力,因为您必须处理“批量中仅相同的分区键”和“仅 100 行”限制。以下版本的DeleteAllRows 执行此操作。

private async Task DeleteAllRows<T>(string table, CloudTableClient client) where T: ITableEntity, new()
    {
        // query all rows
        CloudTable tableref = client.GetTableReference(table);           
        var query = new TableQuery<T>();
        TableContinuationToken token = null;            
        TableBatchOperation batchops = new TableBatchOperation();
        Dictionary<string, Stack<TableOperation>> pendingOperations = new Dictionary<string, Stack<TableOperation>>();
        
        do
        {
            var result = await tableref.ExecuteQuerySegmentedAsync(query, token);
            foreach (var row in result)
            {
               var op = TableOperation.Delete(row);
                if (pendingOperations.ContainsKey(row.PartitionKey))
                {
                    pendingOperations[row.PartitionKey].Push(op);
                }
                else
                {
                    pendingOperations.Add(row.PartitionKey, new Stack<TableOperation>() );
                    pendingOperations[row.PartitionKey].Push(op);
                }                                    
            }
            token = result.ContinuationToken;
        } while (token != null);

        // order by partition key            
        foreach (var key in pendingOperations.Keys)
        {                
            log.Information($"Deleting:{key}");                
            var rowStack = pendingOperations[key];
            int max = 100;
            int current = 0;

            while (rowStack.Count != 0)
            {
                // dequeue in groups of 100
                while (current < max && rowStack.Count > 0)
                {
                    var op = rowStack.Pop();
                    batchops.Add(op);
                    current++;
                }

                //execute and reset
                _ = await tableref.ExecuteBatchAsync(batchops);
                log.Information($"Deleted batch of size:{batchops.Count}");
                current = 0;
                batchops.Clear();
            }
        }                       
    }
Run Code Online (Sandbox Code Playgroud)