Use of enum type in ADO.NET Data Services
This the autumn was possible to communicate about ADO.NET Data Services with the Izhevsk developers community. Except other discussed questions, we have started talking about use of enum type as a part of entity which is used in service based on ADO.NET Data Services. As after that in this question was interested some more person, I decide to take out this information here.
The problem consists in the following. We will assume have decided to create service ADO.NET Data Services and to use in its source the entity containing a field of enum type. Having accessed to such service it is possible to see a strange error.
It is possible to look details of this error. For this purpose it is necessary to setup service.
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class WebDataService1 : DataService<MyDataContext>
{
Having accessed to service again, we will see an error which says that enum type cannot be used in entities for similar services. Unfortunately, this annoying defect in ADO.NET Data Services can seriously impair a life of developers. Let's try solve this problem.
For this purpose we will create entity and enum type which we will use in service:
public enum StateEnum
{
Normal = 1,
Error = 2
}
[DataServiceKey("ID")]
public class SampleEntity
{
public int ID { get; set; }
public string Name { get; set; }
public StateEnum State
{
get;
set;
}
}
Now we will create own data context and standard service ADO.NET Data Services.
public class MyDataContext
{
private static readonly IEnumerable<SampleEntity> Entities = new List<SampleEntity>()
{
new SampleEntity()
{ID = 1, Name = "Name1", State = StateEnum.Normal},
new SampleEntity()
{ID = 2, Name = "Name2", State = StateEnum.Error},
new SampleEntity()
{ID = 3, Name = "Name3", State = StateEnum.Normal},
new SampleEntity()
{ID = 4, Name = "Name4", State = StateEnum.Normal},
new SampleEntity()
{ID = 5, Name = "Name5", State = StateEnum.Normal},
};
public IQueryable<SampleEntity> Data
{
get
{
return Entities.AsQueryable<SampleEntity>();
}
}
}
It is clear, that with such service we will receive an error which saw at the beginning. To avoid an error we will use IgnoreProperties attribute.
[DataServiceKey("ID")]
[IgnoreProperties("State")]
public class SampleEntity
{
public int ID { get; set; }
public string Name { get; set; }
public StateEnum State
{
get { return (StateEnum)StateValue; }
set { StateValue = (int)value; }
}
}
Great! The error has disappeared, but thus value of the given property is not transferred to the client.
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<feed xml:base="http://localhost:4321/WebDataService1.svc/" 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">
<title type="text">Data</title>
<id>http://localhost:4321/WebDataService1.svc/Data</id>
<updated>2009-11-29T06:06:57Z</updated>
<link rel="self" title="Data" href="Data" />
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(1)</id>
<title type="text" />
<updated>2009-11-29T06:06:57Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(1)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">1</d:ID>
<d:Name>Name1</d:Name>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(2)</id>
<title type="text" />
<updated>2009-11-29T06:06:57Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(2)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">2</d:ID>
<d:Name>Name2</d:Name>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(3)</id>
<title type="text" />
<updated>2009-11-29T06:06:57Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(3)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">3</d:ID>
<d:Name>Name3</d:Name>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(4)</id>
<title type="text" />
<updated>2009-11-29T06:06:57Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(4)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">4</d:ID>
<d:Name>Name4</d:Name>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(5)</id>
<title type="text" />
<updated>2009-11-29T06:06:57Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(5)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">5</d:ID>
<d:Name>Name5</d:Name>
</m:properties>
</content>
</entry>
</feed>
Value of enum type is an integer. It is simple type which it is possible to transfer via service. Thus, we do small addition to this entity.
[DataServiceKey("ID")]
[IgnoreProperties("State")]
public class SampleEntity
{
public int ID { get; set; }
public string Name { get; set; }
public int StateValue { get; set; }
public StateEnum State
{
get { return (StateEnum)StateValue; }
set { StateValue = (int)value; }
}
}
After that, the service working with specified entity will ignore State property, but thus on the client will be transferred StateValue. It is easy to be convinced of it if to access to service through a browser.
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<feed xml:base="http://localhost:4321/WebDataService1.svc/" 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">
<title type="text">Data</title>
<id>http://localhost:4321/WebDataService1.svc/Data</id>
<updated>2009-11-29T06:13:47Z</updated>
<link rel="self" title="Data" href="Data" />
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(1)</id>
<title type="text" />
<updated>2009-11-29T06:13:47Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(1)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">1</d:ID>
<d:Name>Name1</d:Name>
<d:StateValue m:type="Edm.Int32">1</d:StateValue>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(2)</id>
<title type="text" />
<updated>2009-11-29T06:13:47Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(2)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">2</d:ID>
<d:Name>Name2</d:Name>
<d:StateValue m:type="Edm.Int32">2</d:StateValue>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(3)</id>
<title type="text" />
<updated>2009-11-29T06:13:47Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(3)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">3</d:ID>
<d:Name>Name3</d:Name>
<d:StateValue m:type="Edm.Int32">1</d:StateValue>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(4)</id>
<title type="text" />
<updated>2009-11-29T06:13:47Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(4)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">4</d:ID>
<d:Name>Name4</d:Name>
<d:StateValue m:type="Edm.Int32">1</d:StateValue>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:4321/WebDataService1.svc/Data(5)</id>
<title type="text" />
<updated>2009-11-29T06:13:47Z</updated>
<author>
<name />
</author>
<link rel="edit" title="SampleEntity" href="Data(5)" />
<category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">5</d:ID>
<d:Name>Name5</d:Name>
<d:StateValue m:type="Edm.Int32">1</d:StateValue>
</m:properties>
</content>
</entry>
</feed>
The last, that it is necessary to make is to inform client library on, how to use similar fields. For this purpose on the client side we declare the necessary enum type, in a partial class we will add the necessary property and we will specify IgnoreProperties attribute.
public enum StateEnum
{
Normal = 1,
Error = 2
}
[IgnoreProperties("State")]
public partial class SampleEntity
{
public StateEnum State
{
get { return (StateEnum)StateValue; }
set { StateValue = (int)value; }
}
}
Now at the client side it is possible to access to the necessary property and to receive value of enum type.
class Program
{
static void Main(string[] args)
{
var context = new MyDataContext(new Uri(@"http://localhost:4321/WebDataService1.svc/"));
foreach (var entity in context.Data)
{
Console.WriteLine(entity.State);
}
Console.Read();
}
}
Certainly, the presented decision does not pretend to be the elegant decision, but can be usable in some cases.
Source: