我的扩展方法可以变得更好吗? BlockBlobClient GetBlockById dotnet

问题描述 投票:0回答:1

我为 BlockBlobClient 做了一个扩展方法,通过块 ID 获取特定块,我想知道是否可以调整此代码片段以提高性能/其他东西

public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
    var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
    var blockList = blockListResponse.Value.CommittedBlocks.ToList();
            
    var currentBlock = blockList.FirstOrDefault(a => a.Name == blockId);

    if (currentBlock.Name == null)
    {
        throw new InvalidOperationException($"Could not find BlockId {blockId}");
    }
            
    var length = currentBlock.SizeLong;
    var index = blockList.FindIndex(a => a.Name == blockId);

    var offset = 0L;
    for (var i = 0; i < index; i++)
    {
        offset += blockList[i].SizeLong;
    }

    var options = new BlobDownloadOptions()
    {
        Range = new HttpRange(offset, length)
    };

    var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);

    return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}
c# azure blob storage block
1个回答
2
投票

唯一真正突出的是

blockList
的多次迭代(3次)。

  1. blockList.FirstOrDefault(a => a.Name == blockId)
  2. blockList.FindIndex(a => a.Name == blockId)
  3. for (var i = 0; i < index; i++)

您可以通过单次迭代来完成此操作,就像这样。

public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
    var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
    var blockList = blockListResponse.Value.CommittedBlocks.ToList();

    var length = 0L
    var offset = 0L;

    // iterate over all blocks until we find the block we want.
    foreach (var block in blockList){
        if (block.Name == blockId){
            length = block.SizeLong;
            break;
        }

        // We haven't found the block we want yet so update the offset.
        offset += block.SizeLong;
    }

    // Check if we found the block we were looking for.
    if (length == 0)
    {
        throw new InvalidOperationException($"Could not find BlockId {blockId}");
    }
            
    var options = new BlobDownloadOptions()
    {
        Range = new HttpRange(offset, length)
    };

    var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);

    return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}

注意我没有在本地运行这段代码,甚至没有尝试编译它,所以可能会有错误,但这个想法是合理的。

更新我错过了一个迭代:

blockListResponse.Value.CommittedBlocks.ToList();

当然,调用 list 可以防止对

CommittedBlocks
的任何重复调用,但这可能会更有效率。

假设

blockListResponse.Value.CommittedBlocks
返回 IEnumerable` 你甚至可以删除这个...

public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
    var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
    var blockList = blockListResponse.Value.CommittedBlocks;

    var length = 0L
    var offset = 0L;

    // iterate over all blocks until we find the block we want.
    var blockListEnumerator = blockList.GetEnumerator();
    while (blockListEnumerator.MoveNext())
    {
        var block = blockListEnumerator.Current as <Insert type of block here>;

        if (block.Name == blockId){
            length = block.SizeLong;
            break;
        }

        // We haven't found the block we want yet so update the offset.
        offset += block.SizeLong;
    }

    // Check if we found the block we were looking for.
    if (length == 0)
    {
        throw new InvalidOperationException($"Could not find BlockId {blockId}");
    }
            
    var options = new BlobDownloadOptions()
    {
        Range = new HttpRange(offset, length)
    };

    var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);

    return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}
© www.soinside.com 2019 - 2024. All rights reserved.