views:

483

answers:

1

I'm getting a strange error while trying to select a row from a table under Windows Azure Table Storage. The exception "An item with the same key has already been added." is being thrown even though I'm not inserting anything. The query that is causing the problem is as follows:

var ids = new HashSet<string>() { id };
var fields = new HashSet<string> {"@all"};
using (var db = new AzureDbFetcher())
{
     var result = db.GetPeople(ids, fields, null);
}

public Dictionary<string, Person> GetPeople(HashSet<String> ids, HashSet<String> fields,     CollectionOptions options)
{
    var result = new Dictionary<string, Person>();
    foreach (var id in ids)
    {
         var p = db.persons.Where(x => x.RowKey == id).SingleOrDefault();
         if (p == null)
         {
                continue;
         }
       // do something with result
    }
}

As you can see, there's only 1 id and the error is thrown right at the top of the loop and nothing is being modified.

However, I'm using "" as the Partition Key for this particular row. What gives?

A: 

You probably added an object with the same row key (and no partition key) to your DataServiceContext before performing this query. Then you're retrieving the conflicting object from the data store, and it can't be added to the context because of the collision.

The context tracks all object retrieved from the Tables. Since entities are uniquely identified by their partitionKey/rowKey combination, a context, like the tables, cannot contain duplicate partitionkey/rowkey combinations.

Possible causes of such a collison are:

  • Retrieving an entity, modifying it, and then retrieving it again using the same context.
  • Adding an entity to the context, and then retrieving one with the same keys.

In both cases, the context the encounters it's already tracking a different object which does however have the same keys. This is not something the context can sort out by itself, hence the exception.

Hope this helps. If you could give a little more information, that would be helpful.

Rik
nope, i've checked the contents of the table. RowKey is unique as I use DateTime.UtcNow. And I'm not adding anything back into the table. Hence, the strange exception.
seanlinmt
The collision is not happening in the table; it's happening in the context. Check the contents of the context.
Rik
nothing is being modified, there's only 1 entry in ids and it happens right at the top.If decided to leave the RowKey empty and use the PartitionKey as the unique identifier now...
seanlinmt
but ok i'll have a look at the context again next time i have a chance...
seanlinmt
Does using the partition key instead solve your problem?
Rik
It seems to solve the problem..... Another point to note is that previously the partitionKey that I use was either an empty string or a single character and the rowkey is always the utcTime. Now the partitionKey is the utcTime and the RowKey is always empty.
seanlinmt