I’ve seen this question quite often on the Astoria forums and wanted to write something down so that our users can gain from the discussions that go on in our forums. We will discuss how one deals with entities ( tables / records / resources ) that participate in an inheritance hierarchy. We shall take the following Data Model to discuss some key scenarios involving the Client Library.
//Base Class [DataServiceKey("PersonID")] public class Person { public int PersonID { get; set; } public string Name { get; set; } } //Derived Class public class Employee : Person { public int EmployeeID { get; set; } }
And you expose an IQueryable<Person> from your data source,
public class InheritedProvider { static List<Person> _people; private static void Initialize() { _people = new List<Person>(){ new Person { PersonID =1, Name="Phani" }, new Employee { PersonID =2, EmployeeID =3, Name ="Raj" } }; } public IQueryable<Person> People { get { if (_people == null) Initialize(); return _people.AsQueryable<Person>(); } } }
Browsing to the /People endpoint of the service gives you :
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <feed …Namespace Declarations… > <title type="text">People</title> <id>http://localhost:13975/Inheritance.svc/People</id> <updated>2008-12-23T20:56:47Z</updated> <link rel="self" title="People" href="People" /> <entry> <id>http://localhost:13975/Inheritance.svc/People(1)</id> <title type="text" /> <updated>2008-12-23T20:56:47Z</updated> <author> <name /> </author> <link rel="edit" title="Person" href="People(1)" />
<category term="Repro.Person" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml"> <m:properties> <d:PersonID m:type="Edm.Int32">1</d:PersonID> <d:Name>Phani</d:Name> </m:properties> </content> </entry> <entry> <id>http://localhost:13975/Inheritance.svc/People(2)</id> <title type="text" /> <updated>2008-12-23T20:56:47Z</updated> <author> <name /> </author> <link rel="edit" title="Person" href="People(2)" />
<category term="Repro.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml"> <m:properties> <d:PersonID m:type="Edm.Int32">2</d:PersonID> <d:Name>Raj</d:Name> <d:EmployeeID m:type="Edm.Int32">3</d:EmployeeID> </m:properties> </content> </entry> </feed>
As you can see , the <Category> element of an <entry> element represents the Entity Type that this <entry> represents.
Consider the following snippet of Client Code :
DataServiceContext dsc = new DataServiceContext(new Uri("URI_TO_DATASERVICE")); Employee newEmployee = new Employee() {Name = "Peter Qian"}; dsc.AddObject("People", newEmployee); dsc.SaveChanges();
<entry xmlns:d=http://schemas.microsoft.com/ado/2007/08/dataservices xmlns:m=http://schemas.microsoft.com/ado/2007/08/dataservices/metadata xmlns="http://www.w3.org/2005/Atom"> <updated>2008-12-23T21:23:38.5935141Z</updated> <content type="application/xml"> <m:properties> <d:EmployeeID m:type="Edm.Int32">0</d:EmployeeID> <d:Name>Peter Qian</d:Name> <d:PersonID m:type="Edm.Int32">0</d:PersonID> </m:properties> </content> </entry>
And this causes the Server to respond with :
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"> <code></code> <message xml:lang="en-US">Error processing request stream. Type information must be specified for types that take part in inheritance.</message> </error>
This error is because , as you can see in the request payload , the <category> element which specifies the Entity Type is missing form the Request Payload. Since the Client library doesn’t resolve the Names/Types of the Entities for you , it provides you hooks to customize the name/type resolution so that the right entity type is specified in the payloads.
Main reason , Since we allow POCO , the type hierarchy of entities on the client can be different compared to the server.
In your client code , set the ResolveName and ResolveType Properties on the DataServiceContext instance to override the default type resolution behavior.
ex :
DataServiceContext dsc = new DataServiceContext(new Uri("URI_TO_DATASERVICE")); dsc.ResolveName = delegate(Type entityType) { return entityType.FullName.Replace("<ClientNamespace>", "<ServerNamespace>"); }; dsc.ResolveType = delegate(string entitySetName) { return Type.GetType(entitySetName); }; Employee newEmployee = new Employee() {Name = "Peter Qian"}; dsc.AddObject("People", newEmployee); dsc.SaveChanges();
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m=http://schemas.microsoft.com/ado/2007/08/dataservices/metadata xmlns="http://www.w3.org/2005/Atom"> <category scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" term="ServerNamespace.Employee" /> <updated>2008-12-23T21:52:44.8021175Z</updated> <content type="application/xml"> <m:properties> <d:EmployeeID m:type="Edm.Int32">0</d:EmployeeID> <d:Name>Peter Qian</d:Name> <d:PersonID m:type="Edm.Int32">0</d:PersonID> </m:properties> </content> </entry>