简体   繁体   English

在SQLite.Net中存储DateTimeOffset

[英]Store DateTimeOffset in SQLite.Net

In a WinRT (Windows 8.1 Store App) project, I'm using the SQLite.Net-PCL and SQLiteNetExtensions NuGet packages to store data in a local SQLite database file. 在WinRT(Windows 8.1 Store App)项目中,我使用SQLite.Net-PCL和SQLiteNetExtensions NuGet包将数据存储在本地SQLite数据库文件中。

Several of my data models (aka tables) contain properties of type DateTimeOffset . 我的一些数据模型(也称为表)包含DateTimeOffset类型的属性。 The aim is to store these without losing the offset information . 目的是在不丢失偏移信息的情况下存储这些信息 (Reason for this is that the user can enter timezone information while specifying dates / times, and this information must be stored in the database.) (原因是用户可以在指定日期/时间时输入时区信息,并且此信息必须存储在数据库中。)

I'm aware of the storeDateTimeAsTicks parameter that can be set while creating the SQLiteConnection , setting this to false forces all DateTime properties to be stored as text in ISO format - however, this has no consequences on DateTimeOffset properties, as these are always automatically converted to UTC and stored as a number representing ticks. 我知道可以在创建SQLiteConnection时设置storeDateTimeAsTicks参数,将其设置为false强制所有DateTime属性以ISO格式存储为文本 - 但是,这对DateTimeOffset属性没有影响,因为它们总是自动转换到UTC并存储为代表刻度的数字。

I can think of the following 4 approaches: 我可以想到以下4种方法:

  • Manually convert DateTimeOffset to string properties and store these, or 手动将DateTimeOffset转换为string属性并存储这些,或
  • extract the DateTime and offset (as TimeSpan date type) parts of the DateTimeOffset , and store these in two separate columns, 提取DateTime和偏移(如TimeSpan日期型)的部件DateTimeOffset ,并且这些存储在两个单独的列,

=> but for both approaches, I'll need to add additional properties to the data model, flag the original DateTimeOffset properties with the [Ignore] attribute, and handle manual conversion (in both directions) - since I'd need to apply this to a lot of different data model classes, it seems too hard to maintain. =>但对于这两种方法,我需要向数据模型添加其他属性,使用[Ignore]属性标记原始DateTimeOffset属性,并处理手动转换(在两个方向上) - 因为我需要应用此对很多不同的数据模型类来说,维护起来似乎太难了。

  • Store the DateTime and TimeSpan (offset) parts of the DateTimeOffset in two columns of a separate table, and maintain references to this separate table 存储DateTimeTimeSpan (偏移)的部分DateTimeOffset在一个单独的表中的两列,并维持到单独的表引用

=> but in this case I'd need to define a custom data type (in order to specify how the DateTime and TimeSpan parts should be stored), and cannot use the default .NET DateTimeOffset type =>但是在这种情况下我需要定义一个自定义数据类型(为了指定应该如何存储DateTimeTimeSpan部分),并且不能使用默认的.NET DateTimeOffset类型

  • Use SQLiteNetExtensions' TextBlob attribute to somehow serialize the DateTimeOffset to a single text column 使用SQLiteNetExtensions的TextBlob属性以某种方式将DateTimeOffset序列化为单个文本列

=> but this feels somewhat hacky, I'd need to make sure that only SQLiteNetExtensions' extension methods are used for DB insert / update, and I'd still need an additional string property on all the data model classes... =>但这感觉有点hacky,我需要确保只有SQLiteNetExtensions的扩展方法用于数据库插入/更新,并且我仍然需要在所有数据模型类上增加一个string属性...

So, my question is: Is there a more straigtforward, obvious solution that I'm missing? 所以,我的问题是:我是否缺少一个更为直接,明显的解决方案?

Since nobody came up with potential solutions, but the question still received some attention, I decided to report how I solved the problem: 由于没有人提出可能的解决方案,但问题仍然引起了一些关注,我决定报告我是如何解决问题的:

Approach #1: 方法#1:

The very scenario that raised the original question included a mobile app consisting of 引发原始问题的场景包括一个由以下内容组成的移动应用程序

  • API data model classes (used for serialization to / from JSON and upload to / download from the backend REST service), API数据模型类(用于序列化到/从JSON到上传/从后端REST服务下载),
  • DB data model classes (representing SQLite tables), and DB数据模型类(代表SQLite表)和
  • various ViewModel classes used for the MVVM-style presentation layer 用于MVVM样式表示层的各种ViewModel类

API models and DB models were nearly identical (except for attributes necessary for JSON serialization and SQLite OR mapping), the only structural difference being that properties representing dates / times were of type string in the API classes and DateTimeOffset in the DB classes. API模型和数据库模型几乎相同(除了JSON序列化和SQLite OR映射所需的属性),唯一的结构差异是表示日期/时间的属性在API类中是string类型,在DB类中是DateTimeOffset After downloading data from, and before uploading data to the backend, API and DB models were converted into each other using Automapper. 从中下载数据之后,在将数据上传到后端之前,使用Automapper将API和DB模型相互转换。

I simply removed the string to DateTimeOffset conversion from the Automapper configuration, and modified the DB data model classes so that DateTimeOffset values are represented as string , which implies that they are stored as formatted text in SQLite (fortunately, no date / time calculations on the DB layer were required). 我只是从Automapper配置中删除了stringDateTimeOffset转换,并修改了DB数据模型类,以便DateTimeOffset值表示为string ,这意味着它们在SQLite中存储为格式化文本(幸运的是,没有日期/时间计算需要DB层)。 Since JSON objects received from the backend include timezone information, I could simply pass through those values to the DB models, thus ensuring that DB tables always contain dates / times as fully formatted datetime strings including timezone offset. 由于从后端接收的JSON对象包含时区信息,因此我可以简单地将这些值传递给数据库模型,从而确保数据库表始终包含日期/时间作为完全格式化的日期时间字符串,包括时区偏移量。

Conversion from string to DateTimeOffset now happens when creating ViewModel classes out of DB data models. 从DB数据模型创建ViewModel类时,现在会发生从stringDateTimeOffset转换。 Obviously, this happens more often than before (when converting API models to DB models) resulting in a little overhead, but I can live with that since I don't need to worry about the SQLite data type issue any more. 显然,这种情况比以前更频繁(将API模型转换为数据库模型时)会产生一些开销,但我可以忍受这种情况,因为我不再需要担心SQLite数据类型问题了。

Approach #2: 方法#2:

Since approach #1 may not be applicable to all scenarios, I came up with an alternative solution that is based on the first one of the 4 potential solutions proposed in the original question, but with reduced manual effort: 由于方法#1可能不适用于所有方案,我提出了一个替代解决方案,该解决方案基于原始问题中提出的4个潜在解决方案中的第一个,但减少了手动工作:

I created a custom attribute [DateTimeOffsetSerialize] that can be assigned to DateTimeOffset properties in SQLite data model classes, and a postbuild task that decompiles the assembly after build has finished and scans all classes within the assembly to find those flagged properties. 我创建了一个可以分配给SQLite数据模型类中的DateTimeOffset属性的自定义属性[DateTimeOffsetSerialize] ,以及一个在构建完成后反编译程序集的postbuild任务,并扫描程序集中的所有类以查找那些标记的属性。 For each of these flagged properties, a duplicate property of type string is created automatically that contains the original property's serialized value, and this newly created string property will be used as SQLite table column (the original DateTimeOffset property is automatically flagged with the [Ignore] attribute). 对于这些标记属性中的每一个,将自动创建包含原始属性的序列化值的string类型的重复属性,并且此新创建的string属性将用作SQLite表列(原始DateTimeOffset属性将使用[Ignore]自动标记[Ignore]属性)。

This solution is available as NuGet package , and has been open-sourced on GitHub (the GitHub page also contains details usage instructions). 该解决方案以NuGet包的形式提供 ,并且已在GitHub上开源 (GitHub页面还包含详细的使用说明)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM