Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best work around to fix DateTimeOffset over WCF Data Service issue

I try to create a WCF Data Service for an Entity Framework model, which contains some attributes of type DateTimeOffeset. However the WCF Data Service does not support the type DateTimeOffset as I found out after googling the exception text "The property 'CreationTime' on type 'Task' is of type 'DateTimeOffset' which is not a supported primitive type.'. See server logs for more details. The exception stack trace is: ...".

I'm now considering different approaches to solve this problem including:

  1. change the type to something that can be mapped to DateTime in the database (worst solution)

  2. Leave the column type in the database as DateTimeOffset, Map the column to two attributes in the Entity Framework model, one DateTime and an additional "Offset" attribute of type integer.

I really don't like any of these approaches. Has anyone found a good work around to fix this issue?

like image 536
phatoni Avatar asked Sep 13 '10 13:09

phatoni


2 Answers

Just add the DateTimeOffset type as a KnownType to the EF data contract that contains the CreationTime property, like explained in http://msdn.microsoft.com/en-us/library/ms730167.aspx.

DateTimeOffset is one of the complex .NET types that is actually being handled as a primitive, except for that it is not registered by default as a KnownType to the serializers. So you need to do this manually.

Your code could look like this:

[DataContract]
[KnownType(typeof(DateTimeOffset))]
public class Task
{
    [DataMember]
    private DateTimeOffset CreationTime;
...
like image 197
kroonwijk Avatar answered Oct 13 '22 21:10

kroonwijk


It's a bit of a hack using reflection, but putting the following in the application start up (I used WebActivator) has so far worked for me using October 2011 CTP.

var primitiveResourceTypeMapType = typeof(ResourceType).Assembly.GetType("System.Data.Services.Providers.PrimitiveResourceTypeMap");
Debug.Assert(primitiveResourceTypeMapType != null);
var builtInTypesMappingField = primitiveResourceTypeMapType.GetField("builtInTypesMapping", BindingFlags.NonPublic | BindingFlags.Static);
Debug.Assert(builtInTypesMappingField != null);

var existingMap = ((KeyValuePair<Type, string>[])builtInTypesMappingField.GetValue(null)).ToList();
existingMap.Add(new KeyValuePair<Type, string>(typeof(DateTimeOffset), "Edm.DateTimeOffset"));
existingMap.Add(new KeyValuePair<Type, string>(typeof(DateTimeOffset?), "Edm.DateTimeOffset"));
builtInTypesMappingField.SetValue(null, existingMap.ToArray());
like image 25
Ceri Avatar answered Oct 13 '22 22:10

Ceri