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:
- Clone this repository
- 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!