0
votes

I'm accessing a "Person" entity using Azure Table Storage via OData (WCF Data Service). I was having lots of issues for getting this to work. I was having this error:

Entity code:

public class Person : TableServiceEntity
{
public string Name { get; set; }
... etc

URI: http://127.0.0.1/DataService/PersonDataService.svc/Person

Result:

The server encountered an error processing the request. The exception message is 'On data context type 'PersonDataServiceContext', there is a top IQueryable property 'Person' whose element type is not an entity type. Make sure that the IQueryable property is of entity type or specify the IgnoreProperties attribute on the data context type to ignore this property.'.

After a lot of troubleshooting, I found out through this post that in order to get around this error, I could add to my entity :

1) [DataServiceKey] attribute to add custom Keys (I need [DataServiceKey("PartitionKey", "RowKey")])

2) By looking for a "PersonID" property (This is the only one that works for me)

3) By looking for an "ID" property

No 1 is the only one that works for me. I had to add a "PersonID" column, like this:

Entity code:

public class Person : TableServiceEntity
{
public Guid PersonID { get; set; } //This is absolutely necessary to get around the aforementioned error
public string Name { get; set; }
... etc

I successfully get data via http://127.0.0.1/DataService/PersonDataService.svc/Person or by specifying the PersonID: http://127.0.0.1/DataService/PersonDataService.svc/Person(guid'e4a924d1-a564-45d7-9e3e-fe0396d08f8e')

I would like to specify a custom Primary Key column, such as PartitionKey/RowKey (coming from TableServiceEntity), but using this code does not help:

[DataServiceKey("PartitionKey", "RowKey")]
public class Person : TableServiceEntity
{
public string Name { get; set; }
... etc

Is this a bug? Do I have to follow that convention for every entity that I have? Person => PersonID, Foo => FooID, etc.

I'm using Visual Studio 2012, and Silverlight 5, .NET Framework 4.0.

2

2 Answers

0
votes

This is a sample that is pretty close to what you are trying

Windows Azure Walkthrough: Table Storage

Understanding the Table Service Data Model

Every entry much have a PartitionKey and a RowKey and the combination must be unique. Based on the first link the rowkey can be string.empty.

0
votes

As per WCF Data Service and Azure Table Storage: How can I use PartitionKey / RowKey as primary keys...

This appears to be a limitation of the Reflection Provider, and probably not an intended limitation. I'll file this as a bug internally, but here is a workaround until we get to a fix...

You can use the new modifier to hide pass the desired values through/from the base class:

using System;
using System.Data.Services.Common;

namespace SO.OData
{
    [DataServiceKey("PartitionKey", "RowKey")]
    public class Question : TableServiceEntry
    {
        public new string PartitionKey
        {
            get { return base.PartitionKey; }
            set { base.PartitionKey = value; }
        }

        public new string RowKey
        {
            get { return base.RowKey; }
            set { base.RowKey = value; }
        }

        public string Text { get; set; }
        public User AskedBy { get; set; }
        public DateTimeOffset AskedAt { get; set; }
    }

    public abstract class TableServiceEntry
    {
        public string PartitionKey { get; set; }
        public string RowKey { get; set; }
    }
}