使用ServiceStack / OrmLite

时间:2015-09-05 16:27:28

标签: c# sql-server servicestack ormlite-servicestack nodatime

我使用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

1 个答案:

答案 0 :(得分:4)

[CustomField]只是告诉OrmLite在创建表时使用哪个列定义,即它没有提供OrmLite如何处理未知类型的任何指示。

您可以通过注册最新版本v4.0.44中现有的Custom Type Converter来支持新字段类型。