如何配置LiteDb,解决DateTimeOffset作为字典键的类型转换错误?
LiteDatabase 字典键DateTimeOffset序列化问题解决方法
问题根源是LiteDatabase默认会将字典键序列化为字符串,反序列化时无法自动将字符串转回DateTimeOffset,因此抛出Invalid cast from 'System.String' to 'System.DateTimeOffset'错误。你可以通过自定义Bson映射规则,为DateTimeOffset类型指定专属的序列化/反序列化逻辑,无需依赖Unix时间戳。
解决步骤与代码示例
1. 配置自定义Bson映射
使用BsonMapper注册DateTimeOffset的序列化和反序列化逻辑,让LiteDatabase能正确处理该类型作为字典键的场景:
// 自定义Bson映射配置 var mapper = new BsonMapper(); // 注册DateTimeOffset的序列化与反序列化逻辑(两种可选方案) // 方案1:序列化为数据库日期类型 mapper.RegisterType<DateTimeOffset>( serialize: dt => BsonValue.FromDateTime(dt.UtcDateTime), deserialize: bson => new DateTimeOffset(bson.AsDateTime, TimeSpan.Zero) ); // 方案2:序列化为ISO格式字符串(兼容性更强) // mapper.RegisterType<DateTimeOffset>( // serialize: dt => dt.ToString("o"), // deserialize: bson => DateTimeOffset.Parse(bson.AsString) // );
2. 使用自定义映射初始化数据库
创建LiteDatabase实例时传入配置好的mapper:
class Data { public Dictionary<DateTimeOffset, string> Dict { get; set; } public ObjectId Id { get; set; } } void Main() { var dbf = Path.GetTempFileName(); var mapper = new BsonMapper(); mapper.RegisterType<DateTimeOffset>( serialize: dt => BsonValue.FromDateTime(dt.UtcDateTime), deserialize: bson => new DateTimeOffset(bson.AsDateTime, TimeSpan.Zero) ); try { using var db = new LiteDatabase(dbf, mapper); var datas = db.GetCollection<Data>(); var data = new Data { Dict = new() { { DateTimeOffset.Now, "apple" }, { DateTimeOffset.Now.AddDays(1), "pear" } } }; datas.Upsert(data); var got = datas.FindById(data.Id); got.Dump(); } catch (Exception ex) { ex.Dump(); } finally { File.Delete(dbf); } }
说明
通过BsonMapper.RegisterType方法,你可以为任意类型定制序列化规则,包括作为字典键的场景。这样既解决了类型转换错误,又能保持代码的直观性,无需手动处理Unix时间戳转换。
内容的提问来源于stack exchange,提问作者ZorgoZ
相关产品推荐
相关产品推荐

