Entity Group Transactions and Development Storage

Have you gotten the error: InvalidInput One of the request inputs is not valid when performing an Entity Group Transaction against Development Storage?  If so, read on.

Recently, I’ve been working on a Windows Azure project, and it’s wonderful that Azure Table Storage now includes support for “Entity Group Transactions”.

Here's the MSDN Documentation Page that explains how the feature works.  Steve Marx's Blog Posting is a good read, too.

Essentially, this allows one to batch up to 100 insert, update, merge, and delete transactions into a single batch that will either completely succeed or fail.  (All the entities in the the transaction must be in the same partition of the same table, and the payload of the transaction cannot exceed 4MB.)

If you want to use Entity Group Transactions with disparate entity types against Development Storage, there is a problem that you will need to workaround.

Given:

     public class XEntity : TableServiceEntity
    {
        public XEntity(string p, string r)
            : base(p, r) { }
    }

    public class YEntity : TableServiceEntity
    {
        public YEntity(string p, string r)
            : base(p, r) {}
    }

The following Entity Group Transaction will succeed:

     tableServiceContext.AddObject(EntitySetName, new XEntity("Partition1", "Row1"));
    tableServiceContext.AddObject(EntitySetName, new XEntity("Partition1", "Row2"));
    tableServiceContext.SaveChangesWithRetries(SaveChangesOptions.Batch);

However, if the entities include distinct properties (XProp and YProp in this example):

     public class XEntity : TableServiceEntity
    {
        public XEntity(string p, string r)
            : base(p, r) { }

        public string XProp { get; set; }
    }

    public class YEntity : TableServiceEntity
    {
        public YEntity(string p, string r)
            : base(p, r) {}

        public string YProp { get; set; }
    }

The following Entity Group Transaction will fail:

     tableServiceContext.AddObject(EntitySetName, new XEntity("Partition1", "Row1"));
    tableServiceContext.AddObject(EntitySetName, new YEntity("Partition1", "Row2"));
    tableServiceContext.SaveChangesWithRetries(SaveChangesOptions.Batch);

The error will be:

 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="https://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <code>InvalidInput</code>
    <message xml:lang="en-US">0:One of the request inputs is not valid.</message>
</error>

I contacted the Azure team about this issue, and they confirmed that it is a limitation that exists, and will be fixed.

The workaround is simple:

You must store one instance of each entity type appearing in an Entity Group Transaction in the table.  So, do this:

     tableServiceContext.AddObject(EntitySetName, new XEntity("Dummy", "DummyX"));
    tableServiceContext.SaveChangesWithRetries();
    tableServiceContext.AddObject(EntitySetName, new YEntity("Dummy", "DummyY"));
    tableServiceContext.SaveChangesWithRetries();

Whenever your table is empty, and then the above example will work.

Best,

Brian

Comments

  • Anonymous
    July 30, 2012
    Do you know if this has this been fixed yet?
  • Anonymous
    September 03, 2012
    It does not appear to be resolved yet. I'm using the "August 2012" release of the Azure SDK and just ran into this exact issue.Thanks for your post, it saved me quite a bit of possible frustration.