Как рассчитать общий размер контейнеров хранения больших двоичных объектов в учетной записи хранения при использовании нового Azure.Хранение.Большие двоичные объекты

#c# #azure #azure-devops

#c# #azure #azure-devops

Вопрос:

Я использую Microsoft.Azure.Storage.Blob последние год или два, и именно так я вычислял размер всех контейнеров:

     var myStorageAccount = CloudStorageAccount.Parse(myConnectionString, string.Empty));
    var myClient = myStorageAccount.CreateCloudBlobClient();

    var myContainers = myClient.ListContainers();

    containerSize = myContainers .Sum(container => 
      container.ListBlobs(null, true).Cast<CloudBlockBlob>().Sum(blobItem => blobItem.Properties.Length));
  

Однако этот пакет теперь устарел, и я обновил его для использования Azure.Storage.Blobs .

Я попытался использовать пример ListContainers отсюда, но, похоже, для этого нужен C # 8:

 async static Task ListContainers(BlobServiceClient blobServiceClient, 
                                string prefix, 
                                int? segmentSize)
{
    string continuationToken = string.Empty;

    try
    {
        do
        {
            // Call the listing operation and enumerate the result segment.
            // When the continuation token is empty, the last segment has been returned
            // and execution can exit the loop.
            var resultSegment = 
                blobServiceClient.GetBlobContainersAsync(BlobContainerTraits.Metadata, prefix, default)
                .AsPages(continuationToken, segmentSize);
            await foreach (Azure.Page<BlobContainerItem> containerPage in resultSegment)
            {
                foreach (BlobContainerItem containerItem in containerPage.Values)
                {
                    Console.WriteLine("Container name: {0}", containerItem.Name);
                }

                // Get the continuation token and loop until it is empty.
                continuationToken = containerPage.ContinuationToken;

                Console.WriteLine();
            }

        } while (continuationToken != string.Empty);
    }
    catch (RequestFailedException e)
    {
        Console.WriteLine(e.Message);
        Console.ReadLine();
        throw;
    }
}
  

Я также не уверен, что перебор — это правильный способ получить общий размер контейнеров в учетной записи хранилища.

Может кто-нибудь, пожалуйста, помочь? Спасибо.

Комментарии:

1. Насколько я знаю, цикл — это лучший / простой способ рассчитать общий размер вашего контейнера больших двоичных объектов. Дайте мне знать, если вам нужен более подробный ответ о том, как это сделать.

Ответ №1:

Я не знаю лучшего способа, чем перебор больших двоичных объектов. Я изменил приведенный вами пример

который работает в C # 8.0

 async static Task<Dictionary<string, long>> ListContainers(BlobServiceClient blobServiceClient,
                                        string connectionString,
                                        string prefix,
                                        int? segmentSize)
{
    string continuationToken = string.Empty;
    var sizes = new Dictionary<string, long>();
    try
    {

        do
        {
            // Call the listing operation and enumerate the result segment.
            // When the continuation token is empty, the last segment has been returned
            // and execution can exit the loop.
            var resultSegment =
                blobServiceClient.GetBlobContainersAsync(BlobContainerTraits.Metadata, prefix, default)
                .AsPages(continuationToken, segmentSize);
            await foreach (Azure.Page<BlobContainerItem> containerPage in resultSegment)
            {

                foreach (BlobContainerItem containerItem in containerPage.Values)
                {
                    BlobContainerClient container = new BlobContainerClient(connectionString, containerItem.Name);

                    var size = container.GetBlobs().Sum(b => b.Properties.ContentLength.GetValueOrDefault());

                    sizes.Add(containerItem.Name, size);

                    Console.WriteLine("Container name: {0} size: {1}", containerItem.Name.PadRight(30), size);
                }

                // Get the continuation token and loop until it is empty.
                continuationToken = containerPage.ContinuationToken;

                Console.WriteLine();
            }

        } while (continuationToken != string.Empty);

        return sizes;
    }
    catch (RequestFailedException e)
    {
        Console.WriteLine(e.Message);
        Console.ReadLine();
        throw;
    }
}
  

и это для C # 7.x (для компиляции вам просто нужен ToListAsync() метод, который находится в System.Linq.Async пакете NuGet. )

 async static Task<Dictionary<string, long>> ListContainers(BlobServiceClient blobServiceClient,
                                        string connectionString,
                                        string prefix,
                                        int? segmentSize)
        {
            string continuationToken = string.Empty;
            var sizes = new Dictionary<string, long>();
            try
            {

                do
                {
                    // Call the listing operation and enumerate the result segment.
                    // When the continuation token is empty, the last segment has been returned
                    // and execution can exit the loop.
                    var resultSegment =
                        await blobServiceClient.GetBlobContainersAsync(BlobContainerTraits.Metadata, prefix, default)
                        .AsPages(continuationToken, segmentSize).ToListAsync();
                     foreach (Azure.Page<BlobContainerItem> containerPage in resultSegment)
                    {

                        foreach (BlobContainerItem containerItem in containerPage.Values)
                        {
                            BlobContainerClient container = new BlobContainerClient(connectionString, containerItem.Name);

                            var size = container.GetBlobs().Sum(b => b.Properties.ContentLength.GetValueOrDefault());

                            sizes.Add(containerItem.Name, size);

                            Console.WriteLine("Container name: {0} size: {1}", containerItem.Name.PadRight(30), size);
                        }

                        // Get the continuation token and loop until it is empty.
                        continuationToken = containerPage.ContinuationToken;

                        Console.WriteLine();
                    }

                } while (continuationToken != string.Empty);

                return sizes;
            }
            catch (RequestFailedException e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();
                throw;
            }
        }
  

Я только что запустил этот код для .NET 4.8, используя эти пакеты:

 <?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Azure.Core" version="1.4.1" targetFramework="net48" />
  <package id="Azure.Storage.Blobs" version="12.6.0" targetFramework="net48" />
  <package id="Azure.Storage.Common" version="12.5.2" targetFramework="net48" />
  <package id="Microsoft.Bcl.AsyncInterfaces" version="1.1.0" targetFramework="net48" />
  <package id="System.Buffers" version="4.5.0" targetFramework="net48" />
  <package id="System.Diagnostics.DiagnosticSource" version="4.6.0" targetFramework="net48" />
  <package id="System.Linq.Async" version="4.1.1" targetFramework="net48" />
  <package id="System.Memory" version="4.5.3" targetFramework="net48" />
  <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
  <package id="System.Runtime.CompilerServices.Unsafe" version="4.6.0" targetFramework="net48" />
  <package id="System.Text.Encodings.Web" version="4.6.0" targetFramework="net48" />
  <package id="System.Text.Json" version="4.6.0" targetFramework="net48" />
  <package id="System.Threading.Tasks.Extensions" version="4.5.2" targetFramework="net48" />
  <package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
</packages>
  

и все было в порядке.

Комментарии:

1. Спасибо за ваш ответ, а также извините, я должен был быть более точным. Это ожидание каждого (Azure.Page<BlobContainerItem> ContainerPage в resultSegment), которое говорит мне, что мне нужен C # 8.

2. Еще раз спасибо, но все еще проблема. Под ToListAsync и Azure.Page<BlobContainerItem> есть красная волнистая линия, в которой говорится, что они не могут быть найдены. Моя платформа .net Framework для моего проекта равна 4.8.

3. Я запустил его для .NET 4.8 без каких-либо проблем.

4. Очень странно. У меня есть все эти пакеты, и мои версии либо равны, либо немного выше. Я даже проверил свой C # по умолчанию, используя csc -langversion:? и это говорит мне, что я использую C # 8. Ошибка продолжает указывать, отсутствует ли ссылка на сборку или оператор Using для этого ToListAsync. Совершенно запутанный. 🙂

5. Вы пытались создать совершенно новый проект? Вы очистили свое решение? Я запускаю приведенные выше фрагменты для dotnet core 3.1 (C #) и dotnet core 2.x и dotnet framework 4.8 (C # 7.x) без каких-либо проблем.