Skip to main content

Azure Storage (Blob, Queue, Table)

Short Introduction

Azure Storage is Microsoft's cloud storage solution providing highly available, secure, durable, scalable, and redundant storage. It includes Blob storage for unstructured data, Queue storage for messaging, and Table storage for NoSQL structured data.

Official Definition

"Azure Storage is a Microsoft-managed service providing cloud storage that is highly available, secure, durable, scalable, and redundant. Azure Storage includes Azure Blobs (objects), Azure Data Lake Storage Gen2, Azure Files, Azure Queues, and Azure Tables."

Setup and Deployment Steps

Azure CLI Setup

# Create storage account
az storage account create --name mystorageaccount --resource-group myResourceGroup --location eastus --sku Standard_LRS --kind StorageV2

# Get connection string
az storage account show-connection-string --name mystorageaccount --resource-group myResourceGroup

# Create blob container
az storage container create --name mycontainer --account-name mystorageaccount

# Create queue
az storage queue create --name myqueue --account-name mystorageaccount

# Create table
az storage table create --name mytable --account-name mystorageaccount

Typical Usage and Integration with .NET Apps

NuGet Packages

<PackageReference Include="Azure.Storage.Blobs" Version="12.19.1" />
<PackageReference Include="Azure.Storage.Queues" Version="12.17.1" />
<PackageReference Include="Azure.Data.Tables" Version="12.8.2" />

Blob Storage Service

using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;

public interface IBlobStorageService
{
Task<string> UploadBlobAsync(string containerName, string blobName, Stream data);
Task<Stream> DownloadBlobAsync(string containerName, string blobName);
Task DeleteBlobAsync(string containerName, string blobName);
Task<List<string>> ListBlobsAsync(string containerName);
}

public class BlobStorageService : IBlobStorageService
{
private readonly BlobServiceClient _blobServiceClient;

public BlobStorageService(BlobServiceClient blobServiceClient)
{
_blobServiceClient = blobServiceClient;
}

public async Task<string> UploadBlobAsync(string containerName, string blobName, Stream data)
{
var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);
await containerClient.CreateIfNotExistsAsync(PublicAccessType.None);

var blobClient = containerClient.GetBlobClient(blobName);
await blobClient.UploadAsync(data, overwrite: true);

return blobClient.Uri.ToString();
}

public async Task<Stream> DownloadBlobAsync(string containerName, string blobName)
{
var blobClient = _blobServiceClient.GetBlobContainerClient(containerName).GetBlobClient(blobName);
var response = await blobClient.DownloadStreamingAsync();
return response.Value.Content;
}

public async Task<List<string>> ListBlobsAsync(string containerName)
{
var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);
var blobs = new List<string>();

await foreach (var blobItem in containerClient.GetBlobsAsync())
{
blobs.Add(blobItem.Name);
}

return blobs;
}
}

Queue Storage Service

using Azure.Storage.Queues;
using Azure.Storage.Queues.Models;

public class QueueStorageService
{
private readonly QueueServiceClient _queueServiceClient;

public QueueStorageService(QueueServiceClient queueServiceClient)
{
_queueServiceClient = queueServiceClient;
}

public async Task SendMessageAsync(string queueName, string message)
{
var queueClient = _queueServiceClient.GetQueueClient(queueName);
await queueClient.CreateIfNotExistsAsync();
await queueClient.SendMessageAsync(message);
}

public async Task<QueueMessage[]> ReceiveMessagesAsync(string queueName, int maxMessages = 10)
{
var queueClient = _queueServiceClient.GetQueueClient(queueName);
var response = await queueClient.ReceiveMessagesAsync(maxMessages);
return response.Value;
}

public async Task DeleteMessageAsync(string queueName, string messageId, string popReceipt)
{
var queueClient = _queueServiceClient.GetQueueClient(queueName);
await queueClient.DeleteMessageAsync(messageId, popReceipt);
}
}

Table Storage Service

using Azure.Data.Tables;

public class Customer : ITableEntity
{
public string PartitionKey { get; set; } = default!;
public string RowKey { get; set; } = default!;
public string Name { get; set; } = default!;
public string Email { get; set; } = default!;
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
}

public class TableStorageService
{
private readonly TableServiceClient _tableServiceClient;

public TableStorageService(TableServiceClient tableServiceClient)
{
_tableServiceClient = tableServiceClient;
}

public async Task<Customer> CreateCustomerAsync(Customer customer)
{
var tableClient = _tableServiceClient.GetTableClient("Customers");
await tableClient.CreateIfNotExistsAsync();

await tableClient.AddEntityAsync(customer);
return customer;
}

public async Task<Customer> GetCustomerAsync(string partitionKey, string rowKey)
{
var tableClient = _tableServiceClient.GetTableClient("Customers");
var response = await tableClient.GetEntityAsync<Customer>(partitionKey, rowKey);
return response.Value;
}

public async Task<List<Customer>> QueryCustomersAsync(string partitionKey)
{
var tableClient = _tableServiceClient.GetTableClient("Customers");
var customers = new List<Customer>();

await foreach (var customer in tableClient.QueryAsync<Customer>(filter: $"PartitionKey eq '{partitionKey}'"))
{
customers.Add(customer);
}

return customers;
}
}

Service Registration

// Program.cs
using Azure.Storage.Blobs;
using Azure.Storage.Queues;
using Azure.Data.Tables;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("AzureStorage");

builder.Services.AddSingleton(x => new BlobServiceClient(connectionString));
builder.Services.AddSingleton(x => new QueueServiceClient(connectionString));
builder.Services.AddSingleton(x => new TableServiceClient(connectionString));

builder.Services.AddScoped<IBlobStorageService, BlobStorageService>();
builder.Services.AddScoped<QueueStorageService>();
builder.Services.AddScoped<TableStorageService>();

Use Cases

Blob Storage

  • Static website hosting
  • Document and media storage
  • Backup and archival
  • Data lakes for analytics
  • Content distribution

Queue Storage

  • Decoupling application components
  • Background job processing
  • Load leveling
  • Reliable messaging between services

Table Storage

  • Semi-structured NoSQL data
  • Web application data storage
  • User data and metadata
  • Device information storage
  • Logging and telemetry data

When to Use vs Alternatives

Use Azure Storage when

  • Cost-effective storage for large amounts of data
  • Integration with Azure ecosystem is important
  • Simple key-value or blob storage requirements
  • High durability and availability needed

Don't use when

  • Complex relational queries required
  • Strong consistency across partitions needed
  • Real-time analytics requirements
  • ACID transactions required

Alternatives

  • AWS: S3 (Blob), SQS (Queue), DynamoDB (Table)
  • GCP: Cloud Storage, Cloud Tasks, Firestore
  • Azure alternatives: Cosmos DB (more features), Service Bus (advanced messaging)

Market Pros/Cons and Cost Considerations

Pros

  • Very cost-effective storage solution
  • High durability (99.999999999% for LRS)
  • Multiple access tiers (Hot, Cool, Archive)
  • Strong integration with Azure services
  • REST API access from any platform

Cons

  • Limited query capabilities (especially Table Storage)
  • No ACID transactions across partitions
  • Table Storage has limited secondary indexes
  • Queue Storage lacks advanced messaging features

Cost Considerations

  • Blob Storage: ~$0.018/GB/month (Hot), ~$0.01/GB/month (Cool), ~$0.002/GB/month (Archive)
  • Queue Storage: ~$0.50 per million transactions
  • Table Storage: ~$0.50 per million transactions + ~$0.045/GB/month
  • Additional charges for operations, bandwidth, and geo-replication