我使用NodaTime Instant
在我的DTO与ServiceStack中存储日期/时间。我已将DTO中的SQL类型指定为datetimeoffset
,ServiceStack正确地创建了具有该类型的表。但是,保存后,我会收到InvalidCastException
。
简单示例:
public class ItemWithInstant
{
public int Id { get; set; }
public string Name { get; set; }
[CustomField("DateTimeOffset")
public Instant DateCreated { get; set; }
}
在服务中:
public object Post(CreateItemWithInstant request)
{
var dto = request.ConvertTo<ItemWithInstant>();
Db.Save(dto); // ERROR here
return dto;
}
具体错误是 InvalidCastException ,其详细信息为无法将参数值从Instant转换为String。
当数据库类型为DateTimeOffset
时,不知道它为什么要转换为字符串。我是否需要告诉ServiceStack如何将值转换为适用于SQL类型的内容?
感谢@mythz的回答,我创建了一个自定义转换器。我最终还是以DATETIME2
为基础获取了SQL数据类型(不要认为这会带来很大的不同):
public class SqlServerInstantToDatetimeConverter : OrmLiteConverter
{
public override string ColumnDefinition { get { return "DATETIME2"; } }
public override DbType DbType { get { return DbType.DateTimeOffset; } }
public override object ToDbValue(Type fieldType, object value)
{
var instantValue = (Instant) value;
return instantValue.ToDateTimeUtc();
}
public override object FromDbValue(Type fieldType, object value)
{
var datetimeValue = DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc);
return Instant.FromDateTimeUtc(datetimeValue);
}
}
然后我在我的AppHost.cs
文件中注册了它:
Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(Settings.Default.LocalSqlConnectionString, SqlServerDialect.Provider));
SqlServerDialect.Provider.RegisterConverter<Instant>(new SqlServerInstantConverter());
不要忘记FromDbType
覆盖。我最初忘记了它并且没有输出该字段。
另一个警告 - 由于ServiceStack想要本地化所有日期,我必须使用此答案中的信息强制所有日期为DateTimeKind.Local
答案 0 :(得分:4)
[CustomField]
只是告诉OrmLite在创建表时使用哪个列定义,即它没有提供OrmLite如何处理未知类型的任何指示。
您可以通过注册最新版本v4.0.44中现有的Custom Type Converter来支持新字段类型。