I have stored in an Azure Table some enumerations like this
pk rk | en fr de ...
foo 1 | 'Eune' 'Fune' 'Dune' ...
foo 2 | 'Edoe' 'Fdoe' 'Ddoe' ...
bar 1 | 'Unee' 'Unef' 'Trid' ...
bar 2 | 'Diee' 'Dief' 'Died' ...
bar 3 | 'Trie' 'Tref' 'Trid' ...
en
, fr
, de
etc... are the language codes, and respectively the column names in the table.
What kind of TableEntity
should I create in order to load it properly
public class FooEntity : TableEntity
{
public Dictionary<string, string> Descriptions {get; set} // ?
}
and then use them like myFoo["fr"]
... is it possible?
Say I have English GUI and I need to display a Foo
select with Eune
/Edoe
as select values.
Azure Storage Table doesn't support Array, List or Dictionary as an entity property. You can find all the supported properties types here (section "Property Types").
However, you can consider serializing the array/list/dictionary to a string property, and declare a property with [IgnoreProperty] attribute in your TableEntity class to convert the serialized string back to array/list/dictionary.
public class MyEntity : TableEntity
{
public string DicPropertyRaw { get; set; }
[IgnoreProperty]
public Dictionary<string, string> DicProperty
{
get
{
return Deserialize(DicPropertyRaw);
}
set
{
DicPropertyRaw = Serialize(value);
}
}
}
My answer extends Zhaoxing's approach of writing the complex entity property to a JSON and persisting that to Azure CosmosDB.
However, serialization between a string and object in the setter causes the following issues:
Instead, I overrode TableEntity's WriteEntity and ReadEntity methods to write custom serialization and deserialization code that is only called when an entity is retrieved from the CloudTable or committed to it -- so only once for each retrieve, update operation etc.
Code below. I've illustrated a more complex example, where my TableEntity contains a class which in turn contains a dictionary.
public class MeetingLayoutEntity : TableEntity
{
/// <summary>
/// Extends TableEntity, the base class for entries in Azure CosmosDB Table tables.
/// </summary>
public MeetingLayoutEntity() { }
public MeetingLayoutEntity(MeetingLayout layout, string partition, string meetingId)
{
this.Layout = layout;
this.PartitionKey = partition;
this.RowKey = meetingId;
}
// Complex object which will be serialized/persisted as a JSON.
[IgnoreProperty]
public MeetingLayout Layout { get; set; }
public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
{
// This line will write partition key and row key, but not Layout since it has the IgnoreProperty attribute
var x = base.WriteEntity(operationContext);
// Writing x manually as a serialized string.
x[nameof(this.Layout)] = new EntityProperty(JsonConvert.SerializeObject(this.Layout));
return x;
}
public override void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
{
base.ReadEntity(properties, operationContext);
if (properties.ContainsKey(nameof(this.Layout)))
{
this.Layout = JsonConvert.DeserializeObject<MeetingLayout>(properties[nameof(this.Layout)].StringValue);
}
}
}
Learn more about ReadEntity and WriteEntity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With