servicestack.ormlite:使用非类型化api读回时间跨度会导致invalidcastexception

oxiaedzo  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(474)

我让servicestack ormlite(5.1.1)创建表,并持久化包含timespan的对象:

// ...
public TimeSpan _Jobs_VehicleNotificationTime { get; set; }
// ...

当我试着读回它时,我得到一个错误:

System.InvalidCastException: 'Invalid cast from 'System.Int64' to 'System.TimeSpan'.'

该值作为 long 似乎:

但我在使用 FromObjectDictionary 方法:

错误是:

at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at ServiceStack.PlatformExtensions.ObjectDictionaryFieldDefinition.SetValue(Object instance, Object value)
   at ServiceStack.PlatformExtensions.FromObjectDictionary(IReadOnlyDictionary`2 values, Type type)
   at tWorks.Core.CoreServerCommons.Handlers.OrmLiteDbHandler.<>c__DisplayClass65_1.<ReadObjects>b__1(Dictionary`2 x) in D:\[GIT]\Core\CoreServerCommons\Handlers\DbHandlers\OrmLite\OrmLiteDbHandler.cs:line 577

这是虫子还是我遗漏了什么?

r6hnlfcb

r6hnlfcb1#

timespan在ormlite中存储为整数列,以确保它们在所有支持的rdbms中保持精度和行为。如果您使用对象字典中的动态结果集检索它,那么它将只能返回尚未通过ormlite的转换器将其转换回的数据读取器值 TimeSpan ,在这种情况下,您将无法使用servicestack.text的 FromObjectDictionary() 这里的泛型扩展方法不使用ormlite的转换器。

kgsdhlau

kgsdhlau2#

我想我已经解决了这个问题。也许@mythz可以告诉我这是否是完全错误的,但它似乎奏效了:
实现你自己的 TimeSpanAsIntConverter 我首先驳斥了这个想法,因为我错误地解释了mythz,认为如果使用非类型化api,转换器就不相关或不执行。当我实现timespan转换器时,它就像预期的那样工作:

namespace Commons
{
    public class MyTimeSpanConverter : TimeSpanAsIntConverter
    {
        public override string ColumnDefinition => "TIME";
        public override DbType DbType => DbType.Time;

        public override object ToDbValue(Type fieldType, object value)
        {
            TimeSpan timespan = (TimeSpan)value;
            return timespan;
        }

    }
}

然后,在使用该转换器时,使用 TIME 键入而不是bigint,并且在持久化后,看起来一切正常:

测试代码:

public void Test()
    {
        Customer c = new Customer() { Username = "TED ÅÄÖ", DeletedTime = DateTime.MaxValue, MyTimeSpan = new TimeSpan(1, 30, 0) };
        CoreObject co = c;
        long id;
        using (IDbConnection db = _dbFactory.Open())
        {
            var typedApi = db.CreateTypedApi(co.GetType());
            id = typedApi.Insert(co, selectIdentity: true);
        };

        using (IDbConnection db = _dbFactory.Open())
        {
            string tableName = co.GetType().GetModelMetadata().ModelName;
            List<Dictionary<string, object>> results = db.Select<Dictionary<string, object>>($"SELECT * FROM {tableName} where id={id}");
            List<CoreObject> coreObjects = results.Map(x => (CoreObject)x.FromObjectDictionary(co.GetType()));
        }
    }

结果:

这似乎至少解决了我的这个问题-我的时间跨度工作的预期。

相关问题