Using the new C# Azure.Data.Tables SDK with Azure Cosmos DB
Tags: dotnet, csharp, azure, database
Published: 2021-07-05 09:00:39

---
title: Using the new C# Azure.Data.Tables SDK with Azure Cosmos DB
published: true
description: 
tags: dotnet,csharp,azure,database
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l3gtjan4uc33ul48v2ul.png
---
Last month, the [Azure SDK team released a new library for Azure Tables for .NET, Java, JS/TS and Python](https://devblogs.microsoft.com/azure-sdk/announcing-the-new-azure-data-tables-libraries/). This release brings the Table SDK in line with other [Azure SDKs](https://aka.ms/azsdk/guide) and they use the specific Azure Core packages for handling requests, errors and credentials.

[Azure Cosmos DB provides a Table API](https://docs.microsoft.com/en-us/azure/cosmos-db/table-introduction) offering that is essentially Azure Table Storage on steroids! If you need a globally distributed table storage service, Azure Cosmos DB should be your go to choice.

If you're making a choice between Azure Cosmos DB Table API and regular Azure Table Storage, I'd recommend reading the following [article](https://docs.microsoft.com/en-us/azure/cosmos-db/table-introduction#table-offerings).

In this article, I'll show you how we can perform simple operations against a Azure Cosmos DB Table API account using the new Azure.Data.Table C# SDK. Specifically, we'll go over:

- Installing the SDK 💻
- Connecting to our Table Client and Creating a table 🔨
- Defining our entity 🧾
- Adding an entity ➕
- Performing Transactional Batch Operations 💰
- Querying our Table ❓
- Deleting an entity ❌

Let's dive into it!

## Installing the SDK 💻

Installing the SDK is pretty simple. We can do so by running the following *dotnet* command:

```csharp
dotnet add package Azure.Data.Tables
```

If you prefer using a UI to install the NuGet packages, we can do so by right-clicking our C# Project in Visual Studio, click on Manage NuGet packages and search for the **Azure.Data.Tables** package:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/flybf7wsylqsgyd5ckew.png)
 
## Connecting to our Table Client and Creating a table 🔨

The SDK provides us with two clients to interact with the service. A *TableServiceClient* is used for interacting with our table at the account lelvel.

We do this for creating tables, setting access policies etc.

We can also use a *TableClient*. This is used for performing operations on our entities. We can also use the *TableClient* to create tables like so:

```csharp
TableClient tableClient = new TableClient(config["StorageConnection"], "Customers");
            await tableClient.CreateIfNotExistsAsync();
```

To create our Table Client, I'm passing in my storage connection string from Azure and the name of the table I want to interact with. On the following line, we create the table if it doesn't exist.

To get out Storage Connection string, we can do so from our Cosmos DB account under **Connection String**:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ex6lcmaho7t27kpp8we8.png)

When we run this code for the first time, we can see that the table has been created in our Data Explorer:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xs3vsctw2ckscegw7rpc.png)
  

## Defining our entity 🧾

In Table Storage, we create entities in our table that require a *Partition Key* and a *Row Key*. The combination of these need to be unique within our table.

Entities have a set of properties and strongly-typed entities need to extend from the *ITableEntity* interface, which expose Partition Key, Row Key, ETag and Timestamp properties. ETag and Timestamp will be generated by Cosmos DB, so we don't need to set these.

For this tutorial, I'm going to use the above mentioned properties along with two string properties (Email and PhoneNumber) to make up a **CustomerEntity** type.

```csharp
public class CustomerEntity : ITableEntity
{
    public string PartitionKey { get; set ; }
    public string RowKey { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }
}
```

## Adding an entity ➕

To add a new entity into our table, we need to instantiate it and simply call the *.AddEntityAsync()* method to insert it:

```csharp
CustomerEntity customerEntity = new CustomerEntity()
{
     PartitionKey = "Velida",
     RowKey = "Will",
     PhoneNumber = "0123456789",
     Email = "will@test.com"
};

await tableClient.AddEntityAsync(customerEntity);
```

Heading back into our Customers table in Cosmos DB, we can see that the entity was successfully inserted.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4n5ogexwkte78hq4rfx6.png)
 
## Performing Transactional Batch Operations 💰

The table service allows us to make multiple operations within a single batch request.

Transaction are 'all-or-nothing', meaning that if one operation in our batch fails, **they will all fail!** Transactions can perform a mixture of create, delete, update and upsert operations.

Just take note that all operations within a transaction needs to target the same partition key.

In the code snippet below, I'm creating a list of *CustomerEntity* objects that I'm going to insert into my table as a batch create operation.

We then create a new List of type *TableTransactionAction* and add the list of entities we want to include in the batch operation to it. We then use the *.SubmitTransactionAsync()* method to submit the batch operation:

```csharp
string partitionKey = "Velida";
List<CustomerEntity> familyList = new List<CustomerEntity>
{
      new CustomerEntity
      {
            PartitionKey = partitionKey,
            RowKey = "Don",
            PhoneNumber = "0987612345"
      },
      new CustomerEntity
      {
            PartitionKey = partitionKey,
            RowKey = "Jane",
            PhoneNumber = "0987612345"
      },
      new CustomerEntity
      {
            PartitionKey = partitionKey,
            RowKey = "Jan",
            PhoneNumber = "0987601298",
            Email = "jan@test.com"
      }
};

List<TableTransactionAction> addFamilyBatch = new List<TableTransactionAction>();

addFamilyBatch.AddRange(familyList.Select(f => new TableTransactionAction(TableTransactionActionType.Add, f)));

Response<IReadOnlyList<Response>> response = await tableClient.SubmitTransactionAsync(addFamilyBatch);
```

Heading back into our table, we can see the entities have been successfully inserted into our Table:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/utsltlbmgorqe9qaqy8u.png)
 
## Querying our Table ❓

We can query our data in Table storage in a couple of ways. The code snippet below uses a OData expression.

Working with [OData query](https://www.odata.org/getting-started/basic-tutorial/) filters can be a pain, but the SDK provides a helper library that makes it a bit easier. Using *.CreateQueryFilter()*, we can write our OData query like so:

```csharp
Pageable<TableEntity> oDataQueryEntities = tableClient.Query<TableEntity>(filter: TableClient.CreateQueryFilter($"PartitionKey eq {partitionKey}"));

foreach (TableEntity entity in oDataQueryEntities)
{
    Console.WriteLine($"{entity.GetString("PartitionKey")}:{entity.GetString("RowKey")}");
}
```

Running this code, we can see a concatenation of our entities *PartitionKeys* and *RowKeys* like so:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kbnr3ninr233jy5ojysn.png)
 
We can also use LINQ expressions to query our Table. Here, I'm using a LINQ query to retrieve a *CustomerEntity* with a *RowKey* value of "Will":

```csharp
Pageable<CustomerEntity> linqEntities = tableClient.Query<CustomerEntity>(customer => customer.RowKey == "Will");

foreach (var entity in linqEntities)
{
     Console.WriteLine($"{entity.RowKey} {entity.PartitionKey}");
}
```

When this code runs, we can see our entity printed out to us:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bp6dr63uauxsg3lpad2x.png)
 
## Deleting an entity ❌

Deleting entities from our table is just a simple *.DeleteEntityAsync()* call. All we need to do is pass in our *ParitionKey* and *RowKey* value like so:

```csharp
await tableClient.DeleteEntityAsync(partitionKey, "Will");
```



Checking our table, we can see that our entity has been successfully deleted:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dcfdq8qvi7g4lic4d668.png)
 

## Wrapping up

Hopefully after reading this article, you understand that working with the Azure.Data.Tables SDK is pretty straightforward. I like the approach that the Azure SDK team is taking with making it's SDKs more consistent with each other.

Using the Azure.Data.Tables SDK, we can build applications that work with both Azure Cosmos DB table storage and regular table storage, so if you find that you're building an application using regular Table Storage and you're struggling with scale, you can switch to Cosmos DB without any code changes!

If you want to learn more about the Azure.Data.Tables library, check out [this blog post](https://devblogs.microsoft.com/azure-sdk/announcing-the-new-azure-data-tables-libraries/) and [this GitHub repo](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/tables/Azure.Data.Tables/samples)!

Hopefully you found this article useful! As always, if you have any questions, feel free to comment below or ask me on [Twitter](https://twitter.com/willvelida)!

Happy Coding! 💻👨‍💻👩‍💻