System.InvalidCastException in Renaming Azure Container

笑着哭i 提交于 2019-12-24 20:17:17

问题


I am trying to rename a container in azure blob storage. I was able to successfully rename the container. But I noticed in some few cases that during some process. I encountered some error.

Here is the error message.

System.InvalidCastException: 'Unable to cast object of type 'Microsoft.WindowsAzure.Storage.Blob.CloudBlobDirectory' to type 'Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob'.'

Below is my code.

string ContainerName = "old-container-name";
    string NewContainerName = "new-container-name";
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
    CloudBlobContainer container = blobClient.GetContainerReference(ContainerName);
    CloudBlobContainer destcontainer = blobClient.GetContainerReference(NewContainerName);
    destcontainer.CreateIfNotExists(BlobContainerPublicAccessType.Blob);
    IEnumerable<IListBlobItem> IE = container.ListBlobs(blobListingDetails: BlobListingDetails.Metadata);
    foreach (IListBlobItem item in IE)
    {
        CloudBlockBlob blob = (CloudBlockBlob)item;
        CloudBlockBlob destBlob = destcontainer.GetBlockBlobReference(blob.Name);
        destBlob.StartCopyAsync(new Uri(GetSharedAccessUri(blob.Name, container)));
    }

I received the error on this line:

CloudBlockBlob blob = (CloudBlockBlob)item;

Do you guys have a fix on this one? Any tips on how to fix this?


回答1:


The reason you're getting this error is because of the way you're listing the blobs.

IEnumerable<IListBlobItem> IE = container.ListBlobs(blobListingDetails: BlobListingDetails.Metadata);

Above line of code will list both blobs and virtual folders. Virtual folders are represented by CloudBlobDirectory. Since you're trying to cast an object of type CloudBlockBlob as CloudBlobDirectory, you're getting this exception.

To list all blobs in a blob container, please use the following override of ListBlobs method: https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.storage.blob.cloudblobcontainer.listblobs?view=azure-dotnet-legacy.

You will need to pass true for useFlatBlobListing parameter. It will then return only the blobs and not virtual folders.




回答2:


  • Check the type of item before casting.
  • You must await your Task.
  • Always prefer the Async API. Don't mix non-Async and Async APIs (this does mean using the custom ListBlobsAsync method also defined below as there is no single ListBlobsAsync method):

async Task CopyBlobsAsync()
{
    const String ContainerName    = "old-container-name";
    const String NewContainerName = "new-container-name";

    CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString") );
    CloudBlobClient     blobClient     = storageAccount.CreateCloudBlobClient();
    CloudBlobContainer  container      = blobClient.GetContainerReference( ContainerName );
    CloudBlobContainer  destcontainer  = blobClient.GetContainerReference( NewContainerName );

    await destcontainer.CreateIfNotExistsAsync( BlobContainerPublicAccessType.Blob );

    List<IListBlobItem> blobs = await ListBlobsAsync( container ).ConfigureAwait(false);
    List<Task>          tasks = new List<Task>();

    foreach( IListBlobItem item in blobs )
    {
        if( item is CloudBlockBlob blob )
        {
            CloudBlockBlob destBlob = destcontainer.GetBlockBlobReference( blob.Name );
            Uri destUri = new Uri( GetSharedAccessUri( blob.Name, container ) );
            Task task = destBlob.StartCopyAsync( destUri  );
            tasks.Add( task );
        }
    }

    await Task.WhenAll( tasks ).ConfigureAwait(false);
}

// From https://ahmet.im/blog/azure-listblobssegmentedasync-listcontainerssegmentedasync-how-to/
async Task<List<IListBlobItem> ListBlobsAsync( CloudBlobContainer container )
{
    BlobContinuationToken continuationToken = null;
    List<IListBlobItem> results = new List<IListBlobItem>();
    do
    {
        var response = await ListBlobsSegmentedAsync( continuationToken );
        continuationToken = response.ContinuationToken;
        results.AddRange( response.Results );
    }
    while( continuationToken != null );
    return results;
}


来源:https://stackoverflow.com/questions/59150291/system-invalidcastexception-in-renaming-azure-container

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!