SQLite中的NHibernate和Utc日期时间

时间:2012-05-16 03:20:57

标签: c# sqlite nhibernate

让我们考虑一下NHibernate中的以下简单类:

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
       assembly="MyTests.Tests"
       namespace="MyTests.Tests">
    <class name="TestClass" table="TestTable" dynamic-update="true">
    <id name="Id" column="Id" type="UInt64" unsaved-value="0">
    <generator class="native" />
    </id>
    <property name="Date1" type="UtcDateTime"></property>
    </class>
    </hibernate-mapping>

该课程的定义如下。

public class TestClass  {
    virtual public UInt64 Id { get; set; }
    virtual public DateTime? Date1 { get; set; }
}

以下用例在针对MySql和SQLite执行时会产生不同的结果。

    [Test]
    public void Test1() {
        //Get Now without Milliseconds
        DateTime now = DateTime.UtcNow;
        now = new DateTime(now.Ticks - (now.Ticks % TimeSpan.TicksPerSecond), now.Kind);

        TestClass tc1 = new TestClass() { Date1 = now };
        using(ISession s = NewSession(c))
        using(ITransaction tx = s.BeginTransaction()) {
            s.Save(tc1);

            tx.Commit();

        }

        using(ISession s = NewSession(c))
        using(ITransaction tx = s.BeginTransaction()) {
            TestClass tc2 = s.Load<TestClass>(tc1.Id);
            Assert.IsNotNull(tc2);

            Assert.AreEqual(DateTimeKind.Utc, tc1.Date1.Value.Kind, "Checking kinds of tc1");
            Assert.AreEqual(tc1.Date1.Value.Kind, tc2.Date1.Value.Kind, "Comparing Kinds");

            Assert.AreEqual(now, tc2.Date1, "Comparing datetime values");
        }   
    }

当使用的数据库是SQLite时,最后一个断言失败。

当我查看SQLite文件时,我可以看到日期正确(UTC值)。

当它被回读时,它会被DateTimeKind.Utc读取,但是本地时间。

如果我使用MySql,这个问题不会发生。

SQLite中的表是由NHibernate用CreateSchema创建的,由SQLite管理员报告为

CREATE TABLE TestTable (Id  integer primary key autoincrement, Date1 DATETIME)
亲爱的大师,你知道问题和解决方案是什么吗?这似乎是以前必须见过的问题...

由于 Tymek

2 个答案:

答案 0 :(得分:3)

我知道这是一个老问题,但答案可能对其他人有帮助......如果您使用System.Data.SQLite提供程序,则只需在连接字符串中指定void string_algo() { const std::string my_str = "Hello, world, it's a wonderful day"; const auto rng2 = boost::make_iterator_range(my_str.begin(),my_str.begin()+10); boost::to_upper_copy(rng2.begin(),rng2); std::cout << rng2 << std::endl; } 即可。日期现在将被视为UTC。

答案 1 :(得分:0)

我在sqlite和sql server上遇到了类似的问题。我将所有DateTime.Kind更改为未指定,然后它不会更改它。我不确定这是不是我的错误,没有时间进一步分析它。如果您可以隔离问题并证明它是一个错误,那么如果您在bug tracker中报告它就会很棒。