1

The scenario is the following: I receive a message containing a lot of variables, several hundreds. I need to write this to Azure Table storage where the partition key is the name of the individual variables and the value gets mapped to e.g. Value.

Let’s say the payload looks like the following:

public class Payload
{
    public long DeviceId { get; set; }
    public string Name { get; set; }
    public double Foo { get; set; }
    public double Rpm { get; set; }
    public double Temp { get; set; }
    public string Status { get; set; }
    public DateTime Timestamp { get; set; }
}

And my TableEntry like this:

public class Table : TableEntity
{
    public Table(string partitionKey, string rowKey)
    {
        this.PartitionKey = partitionKey;
        this.RowKey = rowKey;
    }

    public Table() {}
    public long DeviceId { get; set; }
    public string Name { get; set; }
    public double Value { get; set; }
    public string Signal { get; set; }
    public string Status { get; set; }
}

In order to write that to Table storage, I need to

var table = new Table(primaryKey, payload.Timestamp.ToString(TimestampFormat))
{
    DeviceId = payload.DeviceId,
    Name = payload.Name,
    Status = payload.Status,
    Value = value (payload.Foo or payload.Rpm or payload.Temp),
    Signal = primarykey/Name of variable ("foo" or "rmp" or "temp"),
    Timestamp = payload.Timestamp
};
var insertOperation = TableOperation.Insert(table);
await this.cloudTable.ExecuteAsync(insertOperation);

I don’t want to copy this 900 times (or how many variables there happen to be in the payload message; this is a fixed number).

I could make a method to create the table, but I will still have to call this 900 times.

I thought maybe AutoMapper could help out.

Ilya Chumakov
  • 23,161
  • 9
  • 86
  • 114
Karsten Strøbæk
  • 643
  • 2
  • 8
  • 17
  • Some additional information. The Payload will always contain all properties. The value of the Signal property in Table, should be the name of the property "put" into Value. For example if payload.Foo is mapped to table.Value, table.Signal should be "Foo". – Karsten Strøbæk May 19 '16 at 06:51

3 Answers3

0

Are they always the same variables? A different approach could be to use DynamicTableEntity in which you basically have a TableEntity where you can fill out all additional fields after the RowKey/PartitionKey Duo:

var tableEntity = new DynamicTableEntity();
tableEntity.PartitionKey = "partitionkey";
tableEntity.RowKey = "rowkey";

dynamic json = JsonConvert.DeserializeObject("{bunch:'of',stuff:'here'}");
foreach(var item in json)
{
    tableEntity.Properties.Add(item.displayName, item.value);
}
// Save etc
Pedro G. Dias
  • 3,162
  • 1
  • 18
  • 30
0

The problem is to map these properties, it is right?

Value = value (payload.Foo or payload.Rpm or payload.Temp),
Signal = primarykey/Name of variable ("foo" or "rmp" or "temp"),

This conditional mapping can be done via Reflection:

object payload = new A { Id = 1 };
object value = TryGetPropertyValue(payload, "Id", "Name"); //returns 1

payload = new B { Name = "foo" };
value = TryGetPropertyValue(payload, "Id", "Name"); //returns "foo"

.

public object TryGetPropertyValue(object obj,  params string[] propertyNames)
{
    foreach (var name in propertyNames)
    {
        PropertyInfo propertyInfo = obj.GetType().GetProperty(name);

        if (propertyInfo != null) return propertyInfo.GetValue(obj);
    }

    throw new ArgumentException();
}

You may map rest of properties (which have equal names in source and destination) with AutoMapper.Mapper.DynamicMap call instead of AutoMapper.Mapper.Map to avoid creation of hundreds configuration maps. Or just cast your payload to dynamic and map it manually.

Ilya Chumakov
  • 23,161
  • 9
  • 86
  • 114
  • Yes, you are correct and sorry for not being clear. Value should be mapped to one of a number of variables/properties from source. So if Rpm is 1 in Payload, Value in Table should be 1. Signal should be mapped to the corresponding name of the property, so Signal = "Rpm". I will try this out. Thank you. – Karsten Strøbæk May 19 '16 at 04:58
0

You can create a DynamicTableEntity from your Payload objects with 1-2 lines of code using TableEntity.Flatten method in the SDK or use the ObjectFlattenerRecomposer Nuget package if you are also worried about ICollection type properties. Assign it PK/RK and write the flattened Payload object into the table as a DynamicTableEntity. When you read it back, read it as DynamicTableEntity and you can use TableEntity.ConvertBack method to recreate the original object. Dont even need that intermediate Table class.

Dogu Arslan
  • 3,292
  • 24
  • 43