1753年之前的日期没有保留日期列

时间:2015-03-02 18:53:20

标签: c# sql-server nhibernate

我试图使用NHibernate来持久化实体,但我的DateTime?属性在1753年之前的日期没有被保留。我知道这是DATETIME这个事实下限,但在这种情况下,我的属性由DATE列支持,根据the docs,该列能够处理0001-01-019999-12-31的日期

如果我试图坚持1752年1月1日,NHibernate会为NULL列插入DateOfBirth

这发生在一个更大的项目中,但我花时间创建了一个这样的小型复制品:

  • 我的localhost上有SQL Server 2012 Express,有一个新的数据库" NhTestDb&#34 ;;
  • 创建一个名为" NHibernateTests"的新类库。在Visual Studio 2012中;
  • 使用NuGet添加NHibernate(4.0.3.4000)和依赖项;
  • 使用NuGet添加NUnit(2.6.4)
  • 将以下hbm文件添加为嵌入式资源:

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateTests" namespace="NHibernateTests">
      <class name="Person">
        <id name="Id">
          <generator class="native" />
        </id>
        <property name="Name" />
        <property name="DateOfBirth" type="Date" />
      </class>
    </hibernate-mapping>
    
  • 将以下代码添加到.cs文件中:

    using System;
    using System.Reflection;
    using NHibernate;
    using NHibernate.Cfg;
    using NHibernate.Dialect;
    using NHibernate.Tool.hbm2ddl;
    using NUnit.Framework;
    
    namespace NHibernateTests
    {
        public class Person
        {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
            public virtual DateTime? DateOfBirth { get; set; }
        }
    
        [TestFixture]
        public class Tests
        {
            private ISessionFactory factory;
    
            [TestFixtureSetUp]
            public void TestFixtureSetUp()
            {
                var configuration = new Configuration();
    
                configuration.DataBaseIntegration(db => 
                {
                    db.ConnectionString = @"data source=.\SQLEXPRESS;Integrated Security=SSPI;Initial Catalog=NhTestDb";
                    db.Dialect<MsSql2012Dialect>();
                });
    
                configuration.AddAssembly(Assembly.GetExecutingAssembly());
                configuration.CurrentSessionContext<NHibernate.Context.ThreadStaticSessionContext>();
    
                factory = configuration.BuildSessionFactory();
    
                using (var schemaCreationSession = factory.OpenSession())
                {
                    new SchemaExport(configuration).Execute(true, true, false, schemaCreationSession.Connection, Console.Out);
                }
            }
    
            [Test]
            public void Can_Persist_DateOfBirth()
            {
                var session = factory.OpenSession();
    
                var person = new Person {Name = "John", DateOfBirth = new DateTime(1752, 1, 1)};
    
                session.Save(person);
                session.Refresh(person);
                session.Dispose();
    
                Assert.That(person.Name, Is.EqualTo("John"));
                Assert.That(person.DateOfBirth, Is.EqualTo(new DateTime(1752, 1, 1)));
            }
        }
    }
    

并且看到测试失败,因为DateOfBirth实际上是null

我已经使用调试器进行了双重检查,DateOfBirth实际上在保存之前就已设置为正确的值。

我已经仔细检查过生成的列实际上是Date,并检查the docs此类型的范围是否足够大;

我还检查了其他属性 是否被保留:请参阅NUnit测试,该测试断言Name属性的持久性。

我已经通过NuGet添加了log4net并配置了NHibernate来输出格式化的SQL,如下所示:

INSERT INTO Person (Name, DateOfBirth) 
VALUES (@p0, @p1);
select SCOPE_IDENTITY();
-- @p0 = 'John' [Type: String (4000)],
-- @p1 = NULL [Type: DateTime (0)]

所以实际上 NHibernate 似乎给我带来了麻烦:它明确地插入了NULL。我通过使用SSMS手动插入一行来进行双重检查,SSMS接受'16000101'作为值。

最后,我使用new DateTime(1900, 1, 1)重新运行测试,该测试保持不变。

结论:我如何让NHibernate在1753年之前坚持下去?

1 个答案:

答案 0 :(得分:0)

我的问题与this one非常相似,我估计只是重复一次。在任何情况下,the answer there by @JimFennel也是我的解决方案。将我的属性映射更改为此...

<property name="DateOfBirth" type="DateTime2">
  <column name="DateOfBirth" sql-type="date" />
</property>

...也解决了我的特殊问题。