【问题标题】:Store DateTimeOffset in SQLite.Net在 SQLite.Net 中存储 DateTimeOffset
【发布时间】:2017-02-01 15:48:22
【问题描述】:

在一个 WinRT(Windows 8.1 应用商店应用)项目中,我使用 SQLite.Net-PCL 和 SQLiteNetExtensions NuGet 包将数据存储在本地 SQLite 数据库文件中。

我的几个数据模型(又名表)包含DateTimeOffset 类型的属性。目的是在不丢失偏移信息的情况下存储这些。 (这样做的原因是用户可以在指定日期/时间的同时输入时区信息,而且这些信息必须存储在数据库中。)

我知道可以在创建 SQLiteConnection 时设置 storeDateTimeAsTicks 参数,将其设置为 false 会强制所有 DateTime 属性以 ISO 格式存储为文本 - 但是,这没有对DateTimeOffset 属性的影响,因为这些属性总是自动转换为 UTC 并存储为代表刻度的数字。

我可以想到以下4种方法:

  • 手动将DateTimeOffset 转换为string 属性并存储这些属性,或者
  • 提取DateTimeOffsetDateTime 和偏移(作为TimeSpan 日期类型)部分,并将它们存储在两个单独的列中,

=> 但是对于这两种方法,我都需要向数据模型添加额外的属性,使用 [Ignore] 属性标记原始的 DateTimeOffset 属性,并处理手动转换(双向) - 因为我d 需要将它应用到很多不同的数据模型类,这似乎太难维护了。

  • DateTimeOffsetDateTimeTimeSpan(偏移)部分存储在单独表的两列中,并维护对该单独表的引用

=> 但在这种情况下,我需要定义自定义数据类型(以指定应如何存储 DateTimeTimeSpan 部分),并且不能使用默认的 .NET DateTimeOffset 类型

  • 使用 SQLiteNetExtensions 的 TextBlob 属性以某种方式将 DateTimeOffset 序列化为单个文本列

=> 但这感觉有点 hacky,我需要确保只有 SQLiteNetExtensions 的扩展方法用于数据库插入/更新,并且我仍然需要在所有数据模型类上附加一个 string 属性...

所以,我的问题是:我是否缺少更直接、更明显的解决方案?

【问题讨论】:

  • 我还没有成功测试过,但是你试过使用SQLite.Net.DateTimeOffset nuGet包吗?使用文档在这里:github.com/mobilemotion/SQLite.Net.DateTimeOffset
  • 感谢@nullPainter - 我自己编写并发布了 Nuget 库,因为没有人能回答我的问题。一旦我有更多时间,我可能应该尽快发布问题的答案......
  • 旁注:DateTimeOffset 几乎与DateTime + "user timezone" 不同。事实上,大多数人关心的部分是时区,或者通常是 DST 周围的行为(偏移量是次要考虑因素)。如果您要存储绝对值,始终映射到同一时刻,那么实际区域并不重要。另一方面,如果偏移量确实发生了任何未来的日期/时间可能会合理地改变(如果 DST 通常被调整),例如对于日历/调度程序,单独存储偏移量不太可能完全有帮助。

标签: c# .net sqlite datetimeoffset


【解决方案1】:

由于没有人提出潜在的解决方案,但这个问题仍然受到了一些关注,我决定报告我是如何解决这个问题的:

方法一:

引发原始问题的场景包括一个移动应用,其中包含

  • API 数据模型类(用于序列化到/从 JSON 以及从后端 REST 服务上传/下载),
  • DB 数据模型类(代表 SQLite 表),以及
  • 用于 MVVM 样式表示层的各种 ViewModel 类

API 模型和 DB 模型几乎相同(除了 JSON 序列化和 SQLite OR 映射所需的属性),唯一的结构差异是表示日期/时间的属性在 API 类中的类型为 stringDateTimeOffset在数据库类中。在从后端下载数据之后,在将数据上传到后端之前,API 和 DB 模型使用 Automapper 相互转换。

我只是从 Automapper 配置中删除了 stringDateTimeOffset 的转换,并修改了 DB 数据模型类,以便将 DateTimeOffset 值表示为 string,这意味着它们作为格式化文本存储在SQLite(幸运的是,不需要对 DB 层进行日期/时间计算)。由于从后端收到的 JSON 对象包含时区信息,我可以简单地将这些值传递给 DB 模型,从而确保 DB 表始终包含日期/时间作为完全格式化的日期时间字符串,包括时区偏移量。

现在,从 DB 数据模型创建 ViewModel 类时,会发生从 stringDateTimeOffset 的转换。显然,这种情况比以前更频繁地发生(将 API 模型转换为 DB 模型时)会产生一点开销,但我可以忍受这种情况,因为我不再需要担心 SQLite 数据类型问题。

方法 #2:

由于方法 #1 可能不适用于所有场景,我想出了一个替代解决方案,它基于原始问题中提出的 4 个潜在解决方案中的第一个,但减少了人工:

我创建了一个自定义属性 [DateTimeOffsetSerialize] 可以分配给 SQLite 数据模型类中的 DateTimeOffset 属性,以及一个在构建完成后反编译程序集并扫描程序集中的所有类以查找那些标记的属性的构建后任务.对于这些标记的属性中的每一个,都会自动创建一个类型为 string 的重复属性,其中包含原始属性的序列化值,并且这个新创建的 string 属性将用作 SQLite 表列(原始 DateTimeOffset 属性会自动用[Ignore] 属性标记)。

此解决方案以NuGet package 提供,一直为open-sourced on GitHub(GitHub 页面也包含详细使用说明)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多