Tuesday, February 19, 2013

Azure Lessons Learned (Part III)

So you’ve been rocking along, adding new features to your Azure table service-based project, including new fields in your table entities, and everything works as it should – locally, using the emulator. Then you deploy to Azure, and you get this ominous gem:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="
http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  
<code>OutOfRangeInput</code>
   <message xml:lang="en-US">One of the request inputs is out of range.
RequestId:0c01939e-1197-4269-aafc-0e873c9b1b20
Time:2013-02-19T14:25:06.6864009Z</message>
</error>

You have to make sure that any new properties you’ve added to your table entities conform to table storage standards, available here: http://msdn.microsoft.com/en-us/library/dd179338.aspx

 

DateTime Values

Almost every time I have received the request input out of range exception has been when a DateTime property is added to an entity, but not defaulted correctly. Normally, if you declare a DateTime, but do not assign a value, it defaults to 1/1/0001, or DateTime.MinValue. However, Azure table storage does not support DateTime with values less than 1/1/1753. So, be sure to default your DateTime column:

this.MyNewDateTimeProperty = new DateTime(1753, 1, 1);

Thursday, February 7, 2013

Azure Lessons Learned (Part II)

I have a goal of posting things I have learned while developing an Azure solution (www.scuddle.com). The latest issue was this exception:

The context is already tracking a different entity with the same resource Uri

The resolution is pretty straight-forward – detach from the entity! I’ll explain…

I am using a custom Azure table storage provider, as many do, that provides functionality to Insert, Delete, Update, and Query tables for stored entities. Throughout the application (in this case, ASP.NET MVC 4), a new instance is created, entities are retrieved and updated, and then the instance is released.

However, if you perform an Update, you will have attached to a table entity, like this:

public void Update(TElement entity)
{
    this._tableServiceContext.AttachTo(this._tableName, entity, "*");
    this._tableServiceContext.UpdateObject(entity);
    this._tableServiceContext.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);
}

After the update, if you attempt to query the table for that same entity, you might get the “context is already tracking” exception, because you have attached to the entity in question, but only if you are using the same instance of your storage provider.

The solution is to detach. In the code below, I am detaching both before the update, which does not throw an exception, and also after the update. By doing so, queries immediately following the update are successful.

public void Update(TElement entity)
{
    this._tableServiceContext.Detach(entity);
    this._tableServiceContext.AttachTo(this._tableName, entity, "*");
    this._tableServiceContext.UpdateObject(entity);
    this._tableServiceContext.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);
    this._tableServiceContext.Detach(entity);
}