This blog describes the usage of the InsertOrMerge operation for Azure Table Storage.
Each entity in Table Storage is defined by the PartitionKey/RowKey combination. InsertOrMerge will insert the entity if it doesn’t exist and, if it exists, it would merge the properties of updated entity with the existing one. For more details, see the Azure Storage blog.
When comparing with the existing table schema, not all properties are required to be specified for this operation. InsertOrMerge only merges the specified properties; the rest of them are ignored. As a result, this feature is very convenient — for instance, when aggregating dashboard data. There might be a background process, which simultaneously assembles various pieces of dashboard data from multiple sources. There is an obvious race condition, which InsertOrMerge solves straight forward.
To demonstrate this, let’s define the following entity that we would like to store in Table Storage.
[sourcecode language=”csharp” padlinenumbers=”true” wraplines=”false” gutter=”false”]
public class Dashboard : TableEntity
{
public string AppleType { get; set; }
public int ApplesCount { get; set; }
public string OrangeType { get; set; }
public int OrangesCount { get; set; }
}
[/sourcecode]
Now, let’s define two other entities that contain only some of the existing properties of the Dashboard entity:
[sourcecode language=”csharp” gutter=”false”]
public class DashboardApple : TableEntity
{
public string AppleType { get; set; }
public int ApplesCount { get; set; }
}
public class DashboardOrange: TableEntity
{
public string OrangeType { get; set; }
public int OrangesCount { get; set; }
}
[/sourcecode]
The following code saves the two entities defined above using the InsertOrMerge operation and then retrieves the full entity.
[sourcecode language=”csharp” gutter=”false” wraplines=”false”]
public async Task<Dashboard> Save(
DashboardApple dashboardApple,
DashboardOrange dashboardOrange)
{
var storageAccount = …
var tableClient = storageAccount.CreateCloudTableClient();
table = tableClient.GetTableReference("Dashboard");
table.CreateIfNotExists();
var t1 = table.ExecuteAsync(TableOperation.InsertOrMerge(dashboardApple));
var t2 = table.ExecuteAsync(TableOperation.InsertOrMerge(dashboardOrange));
await Task.WhenAll(t1, t2);
var tableResult = await table.ExecuteAsync(
TableOperation.Retrieve<Dashboard>(partitionKey, rowKey));
return (Dashboard)tableResult.Result;
}
[/sourcecode]
To test the above code the two entities with an identical PartitionKey/RowKey must be created:
[sourcecode language=”csharp” gutter=”false”]
var dashboardApple = new DashboardApple
{
PartitionKey = "myPartition",
RowKey = "myRow",
AppleType = "GoldenDelicious",
ApplesCount = 5
};
var dashboardOrange = new DashboardOrange
{
PartitionKey = "myPartition",
RowKey = "myRow",
OrangeType = "Naval",
OrangesCount = 10
};
var dashboard = await Save(dashboardApple, dashboardOrange);
[/sourcecode]
This results in a single entity in the table with the following properties:
[sourcecode language=”csharp” gutter=”false”]
{
PartitionKey = "myPartition",
RowKey = "myRow",
AppleType = "GoldenDelicious",
ApplesCount = 5,
OrangeType = "Naval",
OrangesCount = 10
};
[/sourcecode]
The data has been aggregated.