4
votes

I'd like to use for table storage an entity like this:

public class MyEntity
{
    public String Text { get; private set; }
    public Int32 SomeValue { get; private set; }

    public MyEntity(String text, Int32 someValue)
    {
        Text = text;
        SomeValue = someValue;
    }
}

But it's not possible, because the ATS needs

  1. Parameterless constructor
  2. All properties public and read/write.
  3. Inherit from TableServiceEntity;

The first two, are two things I don't want to do. Why should I want that anybody could change some data that should be readonly? or create objects of this kind in a inconsistent way (what are .ctor's for then?), or even worst, alter the PartitionKey or the RowKey. Why are we still constrained by these deserialization requirements?

I don't like develop software in that way, how can I use table storage library in a way that I can serialize and deserialize myself the objects? I think that as long the objects inherits from TableServiceEntity it shouldn't be a problem.

So far I got to save an object, but I don't know how retrieve it:

            Message m = new Message("message XXXXXXXXXXXXX");

            CloudTableClient tableClient = account.CreateCloudTableClient();
            tableClient.CreateTableIfNotExist("Messages");
            TableServiceContext tcontext = new TableServiceContext(account.TableEndpoint.AbsoluteUri, account.Credentials);

            var list = tableClient.ListTables().ToArray();

            tcontext.AddObject("Messages", m);
            tcontext.SaveChanges();

Is there any way to avoid those deserialization requirements or get the raw object?

Cheers.

5

5 Answers

4
votes

The constraints around that ADO.NET wrapper for the Table Storage are indeed somewhat painful. You can also adopt a Fat Entity approach as implemented in Lokad.Cloud. This will give you much more flexibility concerning the serialization of your entities.

5
votes

If you want to use the Storage Client Library, then yes, there are restrictions on what you can and can't do with your objects that you want to store. Point 1 is correct. I'd expand point 2 to say "All properties that you want to store must be public and read/write" (for integer properties you can get away with having read only properties and it won't try to save them) but you don't actually have to inherit from TableServiceEntity.

TableServiceEntity is just a very light class that has the properties PartitionKey, RowKey, Timestamp and is decorated with the DataServiceKey attribute (take a look with Reflector). All of these things you can do to a class that you create yourself and doesn't inherit from TableServiceEntity (note that the casing of these properties is important).

If this still doesn't give you enough control over how you build your classes, you can always ignore the Storage Client Library and just use the REST API directly. This will give you the ability to searialize and deserialize the XML any which way you like. You will lose the all of the nice things that come with using the library, like ability to create queries in LINQ.

2
votes

Just don't use inheritance.

If you want to use your own POCO's, create your class as you want it and create a separate tableEntity wrapper/container class that holds the pK and rK and carries your class as a serialized byte array.

1
votes

You can use composition to achieve what you want. Create your Table Entities as you need to for storage and create your POCOs as wrappers on those providing the API you want the rest of your application code to see. You can even mix in some interfaces for better code.

1
votes

How about generating the POCO wrappers at runtime using System.Reflection.Emit http://blog.kloud.com.au/2012/09/30/a-better-dynamic-tableserviceentity/