SujaySarma.Data.Azure.Tables 8.5.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package SujaySarma.Data.Azure.Tables --version 8.5.0                
NuGet\Install-Package SujaySarma.Data.Azure.Tables -Version 8.5.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SujaySarma.Data.Azure.Tables" Version="8.5.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add SujaySarma.Data.Azure.Tables --version 8.5.0                
#r "nuget: SujaySarma.Data.Azure.Tables, 8.5.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install SujaySarma.Data.Azure.Tables as a Cake Addin
#addin nuget:?package=SujaySarma.Data.Azure.Tables&version=8.5.0

// Install SujaySarma.Data.Azure.Tables as a Cake Tool
#tool nuget:?package=SujaySarma.Data.Azure.Tables&version=8.5.0                

Sujay Sarma's Azure Tables Client SDK


(Azure Storage Tables, Azure Development Storage, Azurite & CosmosDB compatible)

Library Current version
SujaySarma.Data.Azure.Tables Version 8.5.0

Version 8.5.0 adds support for .NET 6.0+. Previously the library was available only for a single version of .NET (whatever was the latest at the time).

About this library

Microsoft keeps changing the library names, calling conventions and provided APIs, too frequently for developers to have a stable and consistent environment to code against. This library is an attempt by me to provide both myself and other developers in the same boat overcome those limitations while writing maintainable and performant code.

While you can just use this library as a wrapper for Microsoft's Azure.Data.Tables library, the true power of this library is when you use its powerful ORM capabilities. Transform your .NET business objects (classes or records) in the blink of an eye to TableEntity-ies and vice-versa. When you do so, you also get to leverage the powerful type-transformation and built-in Json serialization capabilities.

Dependencies

This package only depends on whatever is the current Microsoft library of the day that provides the client APIs to interact with Azure Storage Tables and CosmosDB. Right now, that library is

Dependability and Trustworthiness

  • All the code is MIT licensed and open source. Examine every aspect of what the library does.
  • I use this library in tons of my applications, tools, etc. You can expect bugs to be swiftly fixed.
  • Enhancements happen all the time.
  • If you need help or spot an issue, file a ticket on the Issues section.

Usage

Write your .NET business object as a class or record. For example:

public class Person
{
	public string LastName { get; set; }

	public string FirstName { get; set; }

	public DateTime DateOfBirth { get; set; }

	//...
}

Let's say you want to store this object in an Azure Storage Table (or CosmosDB container) named People, add the following to the top of your class file:

using SujaySarma.Data.Azure.Tables.Attributes;

and add this attribute above your class declaration:

[Table("People")]
public class Person ...

For this table, Microsoft mandates that you define a PartitionKey and a RowKey that can be stored only as strings. There are also restrictions on what characters are valid for these values.

To specify these fields, add the relevant attributes from our SujaySarma.Data.Azure.Tables.Attributes namespace. Let's define our LastName property as the PartitionKey and FirstName as the RowKey:

[PartitionKey]
public string LastName { get; set; }

[RowKey]
public string FirstName { get; set; }

We want to store the DateOfBirth in a table column named DateOfBirth:

[TableColumn("DateOfBirth")]
public DateTime DateOfBirth { get; set; }

Finally, let's add a property to this class named Hobbies as a List<string>. We cannot store such types directly in the underlying table. Therefore, we need to tell the SDK to magically serialize it to Json and store that Json in the table.

[TableColumn("Hobbies", JsonSerialize = true)]
public List<string> Hobbies { get; set; } = new();

The completed class definition becomes:

[Table("People")]
public class Person
{
	[PartitionKey]
	public string LastName { get; set; }

	[RowKey]
	public string FirstName { get; set; }

	[TableColumn("DateOfBirth")]
	public DateTime DateOfBirth { get; set; }

	[TableColumn("Hobbies", JsonSerialize = true)]
	public List<string> Hobbies { get; set; } = new();
}

Let's instantiate an item and provide some data:

Person p = new() 
{
	LastName = "Doe",
	FirstName = "John",
	DateOfBirth = new DateTime(2000, 1, 1),
	Hobbies = new() { "Painting", "Reading" }
};

Now, we need to store this in our tables. If you do not have one already, head over to the Azure Portal and create a new Azure Storage account. Then from its Access Keys blade, copy the connection string under key1. The library provides exactly one class AzureTablesContext, which provides a connection-less paradigm to operate against the underlying Tables API. Initialize it with the connection string from above.

AzureTablesContext tablesContext = new("<connection string>");

Of course, you can store the connection string in your Environment Variables or an appsettings.json or the KeyVault or wherever and use it from there.

You can also use the fluid-style initializers:

  1. To initialize with Development Storage (we are Azurite compatible!). Note that this will use HTTP (not httpS)!!!
AzureTablesContext tablesContext = AzureTablesContext.WithDevelopmentStorage();
  1. To initialize with provided connection string:
AzureTablesContext tablesContext = AzureTablesContext.WithConnectionString("<connection string>");

Insert the item we created into this storage.

tablesContext.Insert<Person>(p);

That's it. If you go to the Storage Browser blade of the storage account, you will find the People table there with the data you set above. Notice how the value of the Hobbies column is the Json-serialized value of the .NET property.

To read it back:

Person? p2 = tablesContext.SelectOnlyResultOrNull<Person>(partitionKey: "Doe", rowKey: "John");

The return of that call will be a Null if it could not find the information requested. Examine the values of the properties in p2 to confirm that all the values you stored earlier have been retrieved correctly.


NOTE: The Tables API stores DateTime values only as UTC. The SujaySarma.Data.Azure.Tables (this) library automatically hard-codes
all DateTime, DateTimeOffset values to UTC while storing them. The value will not change, but it will be dealt with as 'UTC'. If you perform Timezone conversions in your code, you will need to 'unconvert' the value returned from the table back to whatever its original zone was:

DateTime dt = DateTime.SpecifyKind(p2.DateOfBirth, DateTimeKind.Local);

Asynchronous operations

As of v8.x, the SDK supports async operations via the new xxxAsync() methods such as InsertAsync in the AzureTablesContext class. However, do note that the Async fetch operations (eg: SelectAsync<T>) will return IAsyncEnumerable<T> and you need to use your own async foreach() for example to loop through and fetch the results. To help, we do provide two extension methods (they are in the AzureTablesContextExtensions class but will attach to any IAsyncEnumerable<T> instance):

  1. async Task<bool> AnyAsync<T>(this IAsyncEnumerable<T> e, Predicate<T>? validation = null)

This method checks if any item in the IAsyncEnumerable matches the provided condition in the same way as the System.Linq method Any() works.

  1. async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> e)

This method accepts an IAsyncEnumerable<T> and returns a List<T>. It performs the await foreach() for you.


Some typical gotchas

  • When storing arrays/lists/collections of Enums as serialized Json, ensure you set the JsonConverter(typeof(JsonStringEnumConverter)) attribute on the enum definition and not on the property! You set the converter attribute on the property only if it is a single value (not an array/collection).

Powerful features

  • You can store almost any type into a table using this library. If it does not store properly, just add a JsonSerialize = true to the TableColumn attribute.

Happy coding!

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
9.1.0 98 6/26/2024
8.5.0 149 12/19/2023
8.0.0 461 1/9/2023
7.4.0 411 9/16/2022
7.3.0 409 9/8/2022
7.2.0 412 9/8/2022
7.0.0 400 8/28/2022
6.4.0 463 8/4/2022
6.3.5 573 3/24/2022
6.3.0 369 9/9/2021
6.2.2 326 8/20/2021
6.2.0 356 8/18/2021
6.0.0 441 8/13/2021
5.1.5 439 6/30/2021
5.1.0 378 5/6/2021
5.0.0 366 5/2/2021

Version 8.5.0 - Added support for .NET Standard 2.1, .NET versions 5.0+