Azure Docs

Working with Azure Table Storage using .NET

This document provides a comprehensive guide to interacting with Azure Table Storage using the .NET SDK. It covers essential operations such as creating tables, inserting entities, querying data, updating entities, and deleting entities.

Introduction to Azure Table Storage

Azure Table Storage is a NoSQL key-attribute store that accommodates unstructured data. It's a cost-effective way to store large amounts of structured, non-relational data that can be accessed from anywhere in the world. Table storage is a NoSQL datastore that accepts authenticated calls across HTTP or HTTPS from any HTTP client. It is also known as Azure Cosmos DB Table API.

Prerequisites

Setting up the Project

To begin, create a new .NET project (e.g., a Console Application) and install the necessary NuGet package:

dotnet add package Azure.Data.Tables

Connecting to Azure Table Storage

You'll need your storage account connection string or endpoint and key. The connection string is the most common method.

using Azure.Data.Tables;

// Replace with your actual connection string
string connectionString = "YOUR_STORAGE_ACCOUNT_CONNECTION_STRING";
string tableName = "MySampleTable";

// Create a TableServiceClient using the connection string
TableServiceClient tableServiceClient = new TableServiceClient(connectionString);

// Get a TableClient for the specific table
TableClient tableClient = tableServiceClient.GetTableClient(tableName);

// Optionally, create the table if it doesn't exist
tableClient.CreateIfNotExists();
Console.WriteLine($"Table '{tableName}' is ready.");

Entities in Table Storage

Entities are the core units of data in Azure Table Storage. Each entity is a set of properties, similar to a row in a database table. An entity must have at least two properties:

Together, PartitionKey and RowKey form the entity's primary key.

Defining an Entity

You can define your entity as a class that inherits from ITableEntity or by using TableEntity directly.

using Azure;
using Azure.Data.Tables;

public class ProductEntity : ITableEntity
{
    public string PartitionKey { get; set; } = string.Empty;
    public string RowKey { get; set; } = string.Empty;
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }

    public string ProductName { get; set; } = string.Empty;
    public int StockQuantity { get; set; }
    public double Price { get; set; }
}

CRUD Operations

Inserting an Entity

To insert a new entity, create an instance of your entity class and use the AddEntity method.

// Example: Creating and inserting a product entity
ProductEntity product = new ProductEntity
{
    PartitionKey = "Electronics",
    RowKey = "SKU12345",
    ProductName = "Wireless Mouse",
    StockQuantity = 150,
    Price = 25.99
};

try
{
    tableClient.AddEntity(product);
    Console.WriteLine($"Product '{product.ProductName}' added successfully.");
}
catch (RequestFailedException ex)
{
    Console.WriteLine($"Error adding entity: {ex.Message}");
}

Querying Entities

You can query entities using OData filter expressions or LINQ.

Using OData Filter
// Filter to find products in the 'Electronics' partition with quantity > 100
string filter = "PartitionKey eq 'Electronics' and StockQuantity gt 100";
Pageable<ProductEntity> queryResults = tableClient.Query<ProductEntity>(filter: filter);

Console.WriteLine("Products with Stock Quantity > 100 in Electronics:");
foreach (Page<ProductEntity> page in queryResults.AsPages())
{
    foreach (ProductEntity entity in page.Values)
    {
        Console.WriteLine($"- {entity.ProductName} (Stock: {entity.StockQuantity}, Price: {entity.Price})");
    }
}
Using LINQ
// LINQ query to find products with price less than 50
var linqQuery = tableClient.Query<ProductEntity>(e => e.Price < 50.0);

Console.WriteLine("Products with Price < 50:");
foreach (var entity in linqQuery)
{
    Console.WriteLine($"- {entity.ProductName} (Price: {entity.Price})");
}

Updating an Entity

You can update an entity using UpsertEntity (inserts if not exists, updates if exists) or UpdateEntity (only updates if exists).

// Retrieve the entity first to ensure it exists and get ETag
Response<ProductEntity> existingEntityResponse = tableClient.GetEntity<ProductEntity>>("Electronics", "SKU12345");
ProductEntity productToUpdate = existingEntityResponse.Value;

if (productToUpdate != null)
{
    productToUpdate.StockQuantity += 20; // Increase stock
    productToUpdate.Price *= 0.95; // Apply a 5% discount

    try
    {
        // Use UpsertEntity to update or insert
        tableClient.UpsertEntity(productToUpdate, TableUpdateMode.Replace);
        Console.WriteLine($"Product '{productToUpdate.ProductName}' updated successfully.");
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"Error updating entity: {ex.Message}");
    }
}
else
{
    Console.WriteLine("Product not found for update.");
}

Deleting an Entity

To delete an entity, you need its PartitionKey and RowKey.

string partitionKeyToDelete = "Electronics";
string rowKeyToDelete = "SKU12345";

try
{
    tableClient.DeleteEntity(partitionKeyToDelete, rowKeyToDelete);
    Console.WriteLine($"Entity with PartitionKey='{partitionKeyToDelete}' and RowKey='{rowKeyToDelete}' deleted.");
}
catch (RequestFailedException ex)
{
    Console.WriteLine($"Error deleting entity: {ex.Message}");
}

Advanced Concepts

Tip: Design your PartitionKey and RowKey carefully to optimize for your most common query patterns. This is crucial for performance in NoSQL databases.
Important: Be mindful of storage costs. Regularly review and clean up unused tables or entities.

Conclusion

Azure Table Storage provides a scalable and cost-effective solution for managing large volumes of structured NoSQL data. The Azure SDK for .NET simplifies the integration, allowing developers to perform all necessary data operations with ease.