Best work around to fix DateTimeOffset over WCF Da

2019-04-22 01:57发布

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?

4条回答
放荡不羁爱自由
2楼-- · 2019-04-22 02:22

The problem you are seeing is because the XmlSerializer cannot serialize DataTimeOffset. However, if you use the DataContractSerializer, it will handle DateTimeOffset just fine. No need for custom serializers or extra hoops to jump through.

That's what I did and am having no issues.

查看更多
你好瞎i
3楼-- · 2019-04-22 02:25

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());
查看更多
祖国的老花朵
4楼-- · 2019-04-22 02:25

I suggest passing a field from your service that contains TimeZone.GetUtcOffset Method return and then calculating the difference between that and the client's offset and then adding/subtracting that difference from the DateTime returned.

查看更多
来,给爷笑一个
5楼-- · 2019-04-22 02:27

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;
...
查看更多
登录 后发表回答