SujaySarma.Sdk.Orm

Provides ORM (Object/Relational Mapping). If you frequently write code that exchanges data between .NET objects (classes) and Azure Storage Tables and Azure CosmosDB table storage, this is a fast and efficient library for you. I use this library across all of my code-bases and products that have interfaces to Azure-stored data.


Keywords
orm, orm-framework, csharp, azure, azure-storage, cosmosdb-orm, cosmosdb, azure-table-storage
License
MIT
Install
Install-Package SujaySarma.Sdk.Orm -Version 1.6.0

Documentation

Orm-AzureTables

The ORM (Object-Relational Mapping) class library that works with Azure Storage Tables. This will also work equally well with the Azure CosmosDB in Azure Tables mode.


Latest Release: version 1.6

The following changes have been made:

Following feedback from consumers of the package, the dependencies to the other Azure Storage Libraries (queues, files, blobs) were removed. We now have only the reference to the Azure Tables library (in addition to Newtonsoft.Json).

Dead-code and unused code was removed in big chunks. The actual ORM code (done via Reflection) has been re-tuned through the use of additional internal hash-checks, faster loops and fewer metadata lookups. Hydration/Dehydration should now be many times faster.

See instructions below.


Compiling from source

Pre-requisites:

  • .NET Core 3.0 SDK. (>= 3.0.0-preview6-*).
  • Newtonsoft.Json (>= 12.0.2).
  • Microsoft.Azure.Cosmos.Table (>= 1.0.1)

Steps:

  1. Clone this repository
  2. Build the project.

The system will automatically restore any missing dependencies and packages.

Using the SDK

As a first step, you need to set up three environment variables. If the variables are not set, the Orm will default to pre-defined behavior. The variables are as follows:

Environment Variable Expected value Default behavior
SujaySarma.Sdk.Orm::ConnectionString Connection string to the Azure Storage or Azure CosmosDB Throws an ArgumentNullException
SujaySarma.Sdk.Orm::CreateTablesOnStartup true or false true
SujaySarma.Sdk.Orm::UseKeyOnlyTables true or false false

About the variables: If CreateTablesOnStartup is set, on the Orm startup, any tables missing on Azure will be created. This may result in a very slightly slow startup time for your application. Since this code is run in the AzureStorage class' static constructor, the effect will be visible only on the first data access. However, subsequent access to tables will be much faster since the check is bypassed. Otherwise, the existence check is performed on each table access.

When UseKeyOnlyTables is true, the tables created on Azure will contain only the basic Azure Tables schema. The other properties and fields of your business object is serialized as Json and stored in a single text column. Performance with such tables is okay, but this means you cannot query and filter through columns of your data except your partition and row keys. When you set this property to false, you get full tables. Setting this to true also enables use of the AzureStorage.Select(query) method that lets you write arbitrary SELECT queries against your full-storage table.

AzureStorageAccount class With Microsoft splitting up their libraries into several pieces, there is virtually no interoperability between the CloudStorageAccount and StorageCredentials classes between their own SDKs! The AzureStorageAccount class solves this problem and bridges the gap. You do not need to really use it -- as it is leveraged correctly by the existing AzureStorage class that provides all the storage operations. But if you do, it will provide you the right Table, File, Blob and Queue clients for use with individual Azure Storage SDK classes.

AzureStorage class Once you have set up the environment variables and defined your business classes, you can perform DML and query commands through the public methods exposed by the AzureStorage class. For DML operations, the class' overloads support single item operations as well as batched operations (pass an IEnumerable<T> of business objects).

Defining your business classes: When you define your business classes, you must decorate them with the SujaySarma.Sdk.Orm.OrmInfo attribute. This is the only mandatory attribute, though the SDK defines a few more. The simplest implementation is as below:

[OrmInfo( "Cars" )]
public class Car 
{
    [OrmPartitionKeyProperty]
    public string Manufacturer { get; set; }

    [OrmRowKeyProperty]
    public string ModelNumber { get; set; }
    
    public List<string> Features { get; }
    
    public List<string> Colors { get; }
}

(Note that you may specify your keys as either properties of the OrmInfo attribute or using the OrmPartitionKeyProperty and OrmRowKeyProperty attributes on the specific property or field. If you specify both, the Orm will throw an exception (AmbiguousMatchException) when you try to persist or hydrate an object of that type.

When UseKeyOnlyTables is true, the class will be serialized as follows:

Table name: Cars

PartitionKey RowKey RowDataSerialized
Value of Manufacturer property Value of ModelNumber property Combined Json-serialized values of Features and Colors

When UseKeyOnlyTables is false, the class will be serialized as follows:

Table name: Cars

PartitionKey RowKey Features Colors
Value of Manufacturer property Value of ModelNumber property Json-serialized Features Json-serialized Colors

To leave properties out of purview of Orm, annotate them with the OrmIgnoreElement attribute:

[OrmIgnoreElement]
public int inventoryLeft;

If you want to control what is serialized and what is not further strictly, you may set the OrmInfo attribute's OptIn to true. When this is true, the Orm will expect you to annotate each required field or property with the OrmFieldInfo attribute. Elements not annotated with the OrmFieldInfo when OptIn is true will not be persisted/rehydrated by the Orm.

Soft deletes: The Orm SDK allows you to hold data in your tables but never retrieve them. It uses a boolean typed column in your table named IsDeleted (this column is created in all your tables by default). To opt into this behavior, set the OrmInfo attribute's UseSoftDelete to true. Now, when you run a Delete() command on this business object, its IsDeleted column will turn true. Data for IsDeleted=TRUE is never returned to the business object!