"Buyin": { "Id": 95,"PlayerSessionId": 88,"PlayerId": 45,"PlayerName": "Alan","Amount": 888,"BuyinType": "Credits","Description": null,"Authorized": true,"SignPath": "~/Signs/Buyins\\95.png","Payment": null,"CreationDate": "/Date(1477242738042)/" },
如果我在Epoch Converter转换它我得到这个时间:GMT:太阳,2016年10月23日17:12:18.042 GMT
在数据库中查看存储的日期时间似乎是正确的:
95 NULL 1 1 2016-10-23 17:12:18.043
发送响应时,Kind被设置为UTC.
现在我调用一个控制器来获取我的所有数据,并且所有日期都有几个小时添加到它:
{ "Id": 95,"CreationDate": "/Date(1477267938043)/" }
1477267938043 = GMT:周一,2016年10月24日00:12:18.043 GMT
但是,当我请求此对象时,我可以看到实际对象具有正确的日期设置:
但是Kind被设置为Unspecified,所以我认为这导致了问题.
目前我还没有设置任何全球化设置.
所以基本上我的问题是:当ASP.NET MVC从数据库加载日期时有一种方法告诉服务器加载Kind设置为UTC的日期,因为我认为这是问题?
使用Entity Framework保存和加载数据库.
在接受的答案后更新
接受的答案很棒但是我的日期值已经作为UTC日期存储在数据库中,所以我将GetDateTime修改为:
public override DateTime GetDateTime(int ordinal) { var date = base.GetDateTime(ordinal); var utcDate = DateTime.SpecifyKind(date,DateTimeKind.Utc); return utcDate; //return base.GetDateTime(ordinal).ToUniversalTime(); }
解决方法
已经提出了类似的问题,并且答案倾向于暗示进入ObjectContext.ObjectMaterialized
事件,但是对于使用投影的查询,它没有触发.
我将提出的解决方案适用于实体和投影查询,方法是在DbDataReader级别执行转换(由此类查询使用).
为此,我们需要一个拦截GetDateTime
方法的自定义DbDataReader实现.不幸的是,实现DbDataReader派生类需要很多样板代码.幸运的是,我已经创建了一个基类形式,我对Dynamic Translate to avoid C# syntax errors的回答只是将每个方法委托给底层的DbDataReader实例,所以我只是从那里拿它:
abstract class DelegatingDbDataReader : DbDataReader { readonly DbDataReader source; public DelegatingDbDataReader(DbDataReader source) { this.source = source; } public override object this[string name] { get { return source[name]; } } public override object this[int ordinal] { get { return source[ordinal]; } } public override int Depth { get { return source.Depth; } } public override int FieldCount { get { return source.FieldCount; } } public override bool HasRows { get { return source.HasRows; } } public override bool IsClosed { get { return source.IsClosed; } } public override int RecordsAffected { get { return source.RecordsAffected; } } public override bool GetBoolean(int ordinal) { return source.GetBoolean(ordinal); } public override byte GetByte(int ordinal) { return source.GetByte(ordinal); } public override long GetBytes(int ordinal,long dataOffset,byte[] buffer,int bufferOffset,int length) { return source.GetBytes(ordinal,dataOffset,buffer,bufferOffset,length); } public override char GetChar(int ordinal) { return source.GetChar(ordinal); } public override long GetChars(int ordinal,char[] buffer,int length) { return source.GetChars(ordinal,length); } public override string GetDataTypeName(int ordinal) { return source.GetDataTypeName(ordinal); } public override DateTime GetDateTime(int ordinal) { return source.GetDateTime(ordinal); } public override decimal GetDecimal(int ordinal) { return source.GetDecimal(ordinal); } public override double GetDouble(int ordinal) { return source.GetDouble(ordinal); } public override IEnumerator GetEnumerator() { return source.GetEnumerator(); } public override Type GetFieldType(int ordinal) { return source.GetFieldType(ordinal); } public override float GetFloat(int ordinal) { return source.GetFloat(ordinal); } public override Guid GetGuid(int ordinal) { return source.GetGuid(ordinal); } public override short GetInt16(int ordinal) { return source.GetInt16(ordinal); } public override int GetInt32(int ordinal) { return source.GetInt32(ordinal); } public override long GetInt64(int ordinal) { return source.GetInt64(ordinal); } public override string GetName(int ordinal) { return source.GetName(ordinal); } public override int GetOrdinal(string name) { return source.GetOrdinal(name); } public override string GetString(int ordinal) { return source.GetString(ordinal); } public override object GetValue(int ordinal) { return source.GetValue(ordinal); } public override int GetValues(object[] values) { return source.GetValues(values); } public override bool IsDBNull(int ordinal) { return source.IsDBNull(ordinal); } public override bool NextResult() { return source.NextResult(); } public override bool Read() { return source.Read(); } public override void Close() { source.Close(); } public override T GetFieldValue<T>(int ordinal) { return source.GetFieldValue<T>(ordinal); } public override Task<T> GetFieldValueAsync<T>(int ordinal,CancellationToken cancellationToken) { return source.GetFieldValueAsync<T>(ordinal,cancellationToken); } public override Type GetProviderSpecificFieldType(int ordinal) { return source.GetProviderSpecificFieldType(ordinal); } public override object GetProviderSpecificValue(int ordinal) { return source.GetProviderSpecificValue(ordinal); } public override int GetProviderSpecificValues(object[] values) { return source.GetProviderSpecificValues(values); } public override DataTable GetSchemaTable() { return source.GetSchemaTable(); } public override Stream GetStream(int ordinal) { return source.GetStream(ordinal); } public override TextReader GetTextReader(int ordinal) { return source.GetTextReader(ordinal); } public override Task<bool> IsDBNullAsync(int ordinal,CancellationToken cancellationToken) { return source.IsDBNullAsync(ordinal,cancellationToken); } public override Task<bool> ReadAsync(CancellationToken cancellationToken) { return source.ReadAsync(cancellationToken); } public override int VisibleFieldCount { get { return source.VisibleFieldCount; } } }
并构建我们需要的实际类:
class UtcDateTimeConvertingDbDataReader : DelegatingDbDataReader { public UtcDateTimeConvertingDbDataReader(DbDataReader source) : base(source) { } public override DateTime GetDateTime(int ordinal) { return DateTime.SpecifyKind(base.GetDateTime(ordinal),DateTimeKind.Utc); } }
一旦我们有了这个,我们需要使用EF interception将其插入EF基础设施.
我们首先创建一个自定义DbCommandInterceptor派生类:
class UtcDateTimeConvertingDbCommandInterceptor : DbCommandInterceptor { public override void ReaderExecuted(DbCommand command,DbCommandInterceptionContext<DbDataReader> interceptionContext) { base.ReaderExecuted(command,interceptionContext); if (interceptionContext.Result != null && interceptionContext.Exception == null) interceptionContext.Result = new UtcDateTimeConvertingDbDataReader(interceptionContext.Result); } }
public class YourDbContext : DbContext { static YourDbContext() { DbInterception.Add(new UtcDateTimeConvertingDbCommandInterceptor()); } // ... }
我们完成了.