我在 UWP 应用中使用带有扩展的 SQLite.NET 来存储包含 DateTime 字段的对象,结果很奇怪。似乎日期的存储距离它们应该有几个小时的时间,有时会将日期时间的日期推迟到第二天。
我正在存储一个名为 Record 的 POCO 类,其中包含如下所示的 Situation 对象
public class Situation
{
[PrimaryKey, AutoIncrement]
public int SituationId { get; set; }
public DateTime DateTime { get; set; }
public string Description { get; set; }
}
包含这种情况的 Record 类使用 SQLite 通过这样的存储库模式进行存储(我只包含相关方法):
internal class Repository<T> : IRepository<T> where T : class
{
private SQLiteAsyncConnection asyncConn;
public Repository(SQLiteAsyncConnection conn)
{
asyncConn = conn;
}
public async Task<T> GetByIdAsync(int id)
{
var entity = await asyncConn.GetWithChildrenAsync<T>(id);
return entity;
}
public async Task InsertOrUpdateAsync(T entity)
{
await asyncConn.InsertOrReplaceWithChildrenAsync(entity);
}
}
最后,我使用 ConnectionManager 类获得存储库的异步连接:
public class ConnectionManager
{
public static readonly string FileName = "db.sqlite";
private static string path = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "db.sqlite");
public static SQLiteAsyncConnection GetAsyncConnection()
{
var connString = new SQLiteConnectionString(path, storeDateTimeAsTicks: true);
var connWithLock = new SQLiteConnectionWithLock(new SQLitePlatformWinRT(), connString);
return new SQLiteAsyncConnection(() => connWithLock);
}
}
此 AsyncConnection 将日期时间存储为刻度,我怀疑这可能是问题的根源。
在一种情况下,在使用 Repository.InsertOrUpdateAsync 存储 Record 对象之前,Situation.DateTime 具有以下值:
日期时间 = {2016-07-01 12:59:59 PM}
即时报价 = 636029747990010000
但是,使用 Repository.GetByIdAsync 拉取记录,日期时间值如下所示:
日期时间 = {2016-07-01 4:59:59 PM}
即时报价 = 636029891990010000
如您所见,SQLite存储DateTime的方式出了问题。"刻度"字段已更改,导致新日期。我不是 100% 确定为什么会这样。我知道日期时间可能会有准确性问题,但如果日期时间存储为即时报价,那么即时报价字段不应该匹配吗?为什么它们会被改变?
假设我必须将日期时间存储为即时报价,如何解决此问题?我正在考虑将 DateTime 小时设置为 12,这样它就可以在不更改日期的情况下增加或减少几个小时,但这显然并不理想。
任何帮助将不胜感激。 :)
我做了一个演示并使用Ticks来存储DateTime
。会出现同样的问题。我调试了收到的Situation
对象的DateTime
属性。事实证明,DateTime.Kind
是Utc
.所以这是一个时区问题,SQLite 默认将DateTime
转换为 UTC 时间。若要解决此问题,可以使用 DateTime.ToLocalTime 获取正确的本地时间。
以下是代码:
if (situation.DateTime.Kind == DateTimeKind.Utc)
{
situation.DateTime = situation.DateTime.ToLocalTime();
}