#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) без каких-либо проблем.