日期列不会保留 1753 年之前的日期
Date column not being persisted for dates before the year 1753
我正在尝试使用 NHibernate 保留实体,但我的 DateTime?
属性 没有保留 1753 年之前的日期。我知道这是 DATETIME
的下限,但在这种情况下,我的 属性 由 DATE
列支持,根据 the docs 能够处理 0001-01-01
到 9999-12-31
.
如果我尝试坚持 1752 年 1 月 1 日,NHibernate 会为 DateOfBirth
列插入一个 NULL
。
这发生在一个更大的项目中,但我花时间创建了一个像这样的小复现:
- 我的本地主机上有 SQL Server 2012 Express,有一个新的数据库 "NhTestDb";
- 在 Visual Studio 2012 年创建一个名为 "NHibernateTests" 的新 class 库;
- 使用 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 手动插入一行来仔细检查了这一点,它确实接受 '16000101'
作为值。
最后,我用 new DateTime(1900, 1, 1)
重新 运行 测试,结果一直很好。
底线:如何让 NHibernate 保留 1753 年之前的日期?
我的问题与 this one, just about a duplicate I guess. In any case, the answer there by @JimFennel 非常相似,对我来说也是一个解决方案。将我的 属性 映射更改为此...
<property name="DateOfBirth" type="DateTime2">
<column name="DateOfBirth" sql-type="date" />
</property>
...也解决了我的特殊问题。
我正在尝试使用 NHibernate 保留实体,但我的 DateTime?
属性 没有保留 1753 年之前的日期。我知道这是 DATETIME
的下限,但在这种情况下,我的 属性 由 DATE
列支持,根据 the docs 能够处理 0001-01-01
到 9999-12-31
.
如果我尝试坚持 1752 年 1 月 1 日,NHibernate 会为 DateOfBirth
列插入一个 NULL
。
这发生在一个更大的项目中,但我花时间创建了一个像这样的小复现:
- 我的本地主机上有 SQL Server 2012 Express,有一个新的数据库 "NhTestDb";
- 在 Visual Studio 2012 年创建一个名为 "NHibernateTests" 的新 class 库;
- 使用 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 手动插入一行来仔细检查了这一点,它确实接受 '16000101'
作为值。
最后,我用 new DateTime(1900, 1, 1)
重新 运行 测试,结果一直很好。
底线:如何让 NHibernate 保留 1753 年之前的日期?
我的问题与 this one, just about a duplicate I guess. In any case, the answer there by @JimFennel 非常相似,对我来说也是一个解决方案。将我的 属性 映射更改为此...
<property name="DateOfBirth" type="DateTime2">
<column name="DateOfBirth" sql-type="date" />
</property>
...也解决了我的特殊问题。