If you want to insert a row into an Azure Table Storage table the easiest way is to create a new class with the desired fields that inherits from TableEntity perform an insert operation with it using the storage client.

This works fine as long as long as the properties of your class are ones that are supported by the Table Storage client, if you have properties that aren’t supported then the row will insert but without the unsupported properties.

If you’d like to insert unsupported properties such as a List or Dictionary then you’ll need to override the WriteEntity and ReadEntity methods of your TableEntity to process these properties as you’d like. In my case the best option was store them as a JSON string.

The below code is based on that found here, the properties that you want to store as JSON are decorated with the EntityJsonPropertyConverter attribute and WriteEntity and ReadEntity overrides then handle the serializing/deserializing of the JSON.

ReceiptRequestEntity.cs

public class ReceiptRequestEntity : TableEntity
{
	public ReceiptRequestEntity(string emailAddress, string functionInvocationId)
	{
		this.PartitionKey = emailAddress;
		this.RowKey = functionInvocationId;
	}

	public bool? OptIn { get; set; }

	public string Type { get; set; }

	public string ActionType { get; set; }

	public int? SequenceId { get; set; }

	[EntityJsonPropertyConverter]
	public Dictionary<int, string> Products { get; set; }

	public string RedirectUri { get; set; }

	[EntityJsonPropertyConverter]
	public bool IsValid
	{
		get
		{
			bool _isValid = true;

			if (string.IsNullOrEmpty(PartitionKey) || string.IsNullOrEmpty(Type) || string.IsNullOrEmpty(ActionType) || OptIn == null || SequenceId == null || Products.Count == 0)
			{
				_isValid = false;
			}

			return _isValid;
		}
	}

	public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
	{
		var results = base.WriteEntity(operationContext);
		EntityJsonPropertyConverter.Serialize(this, results);
		return results;
	}

	public override void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
	{
		base.ReadEntity(properties, operationContext);
		EntityJsonPropertyConverter.Deserialize(this, properties);
	}
}

EntityJsonPropertyConverterAttribute.cs

[AttributeUsage(AttributeTargets.Property)]
public class EntityJsonPropertyConverterAttribute : Attribute
{
	public EntityJsonPropertyConverterAttribute()
	{
	}
}

public class EntityJsonPropertyConverter
{
	public static void Serialize<TEntity>(TEntity entity, IDictionary<string, EntityProperty> results)
	{
		entity.GetType().GetProperties()
			.Where(x => x.GetCustomAttributes(typeof(EntityJsonPropertyConverterAttribute), false).Count() > 0)
			.ToList()
			.ForEach(x => results.Add(x.Name, new EntityProperty(JsonConvert.SerializeObject(x.GetValue(entity)))));
	}

	public static void Deserialize<TEntity>(TEntity entity, IDictionary<string, EntityProperty> properties)
	{
		entity.GetType().GetProperties()
			.Where(x => x.GetCustomAttributes(typeof(EntityJsonPropertyConverterAttribute), false).Count() > 0)
			.ToList()
			.ForEach(x => x.SetValue(entity, JsonConvert.DeserializeObject(properties[x.Name].StringValue, x.PropertyType)));
	}
}

Leave a Reply

Your e-mail address will not be published. Required fields are marked *