在SQLite.Net中存储DateTimeOffset

时间:2017-02-01 15:48:22

标签: c# .net sqlite datetimeoffset

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

我的一些数据模型(aka表)包含DateTimeOffset类型的属性。目的是存储这些而不会丢失偏移信息。 (原因是用户可以在指定日期/时间时输入时区信息,并且此信息必须存储在数据库中。)

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

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

  • 手动将DateTimeOffset转换为string属性并存储这些属性,或
  • 提取DateTime的{​​{1}}和偏移量(TimeSpan日期类型)部分,并将这些部分存储在两个单独的列中,

=>但对于这两种方法,我需要向数据模型添加其他属性,使用DateTimeOffset属性标记原始DateTimeOffset属性,并处理手动转换(在两个方向上) - 因为我需要将它应用于许多不同的数据模型类,它似乎太难维护。

  • [Ignore]的{​​{1}}和DateTime(偏移)部分存储在单独表格的两列中,并维护对此单独表格的引用

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

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

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

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

1 个答案:

答案 0 :(得分:5)

由于没有人提出可能的解决方案,但问题仍然引起了一些关注,我决定报告我是如何解决问题的:

方法#1:

提出原始问题的方案包括一个由

组成的移动应用程序
  • API数据模型类(用于序列化到/来自JSON并上传到/从后端REST服务下载),
  • DB数据模型类(表示SQLite表)和
  • 用于MVVM样式表示层的各种ViewModel类

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

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

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

方法#2:

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

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

此解决方案以NuGet package提供,并且已open-sourced on GitHub(GitHub页面还包含详细使用说明)。