本文介绍了NHibernate 中的 DateTime 精度和 NHibernate SchemeExport 中对 DateTime2 的支持的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

然后我使用 Fluent NHibernate 及其自动映射功能来映射以下简化的 POCO 类:

I am then using Fluent NHibernate and its automapping feature to map the the following simplified POCO class:

public class Foo
{
public virtual int Id { get; set; }
public virtual datetime CreatedDateTime { get; set; }
}

默认情况下,CreatedDateTime 字段将映射到 SQL 日期时间.但是,如果我进行测试以检查实体是否正确创建,则会失败.这是因为 DateTime 字段的精度不会一直保持到 SQL 数据库.我认为这背后的原因是 MS SQL Server DateTime 只能通过舍入到 .000、.003 或 .007 的增量来保持毫秒精度(请参阅 http://msdn.microsoft.com/en-us/library/ms187819.aspx).出于这个原因,NHibernate 在保存到商店时会截断毫秒.这导致我的测试在检查字段是否正确持久时失败,因为我的 .NET DateTime 保持其毫秒,但 DateTime 在保存丢失其毫秒后恢复,因此两者并不真正相等.

The CreatedDateTime field will map to a SQL DateTime by default. However if I do a test to check that the entity is being created correctly it fails. This is because the precision of the DateTime field is not maintained through to the SQL database. I undersatnd the reason behind this to be that a MS SQL Server DateTime can only hold milisecond precision by rounded to increments of .000, .003, or .007 (see http://msdn.microsoft.com/en-us/library/ms187819.aspx). For this reason NHibernate truncates the miliseconds when saving to the store. This results in my test failing when checking that the fields where persisted correctly as my .NET DateTime holds its miliseconds but the DateTime retrived after the save has lost its miliseconds and therefore the two are not truely equal.

为了克服这个问题,我向 Foo 对象添加了以下映射:

To overcome this problem I have added the following mapping to the Foo object:

public class FooMap : IAutoMappingOverride<Foo>
{
    public void Override(AutoMapping<Foo> mapping)
    {
        mapping.Map(f => f.CreatedDateTime).CustomType("datetime2");
    }
}

我知道这种映射使 NHibernate 将 CreatedDateTime 持久化为 datetime2 的 SQL 类型,它可以存储 .NET DateTime 可以存储的完整精度.这很有效,现在测试通过了.

I understand that this mapping makes NHibernate persist the CreatedDateTime to a SQL type of datetime2, which can store the full precision that a .NET DateTime can.This works a treat and the test now passes.

然而,一次通过又一次失败:我检查模式导出的测试现在失败,并出现以下错误:

However with one pass comes another fail: My test that checks the schema export now fails with the following error:

System.ArgumentException : Dialect does not support DbType.DateTime2
Parameter name: typecode

具有以下堆栈跟踪:

at NHibernate.Dialect.TypeNames.Get(DbType typecode)
at NHibernate.Dialect.Dialect.GetTypeName(SqlType sqlType)
at NHibernate.Mapping.Column.GetDialectTypeName(Dialect dialect, IMapping mapping)
at NHibernate.Mapping.Table.SqlCreateString(Dialect dialect, IMapping p, String defaultCatalog, String defaultSchema)
at NHibernate.Cfg.Configuration.GenerateSchemaCreationScript(Dialect dialect)
at NHibernate.Tool.hbm2ddl.SchemaExport..ctor(Configuration cfg, IDictionary`2 configProperties)
at NHibernate.Tool.hbm2ddl.SchemaExport..ctor(Configuration cfg)

代码使用 NHibernate.Tool.hbm2ddl.SchemaExport 对象来调用 Execute 方法.

The code uses the NHibernate.Tool.hbm2ddl.SchemaExport object to call the Execute method.

我使用的是 Fluent v1 和 NHibernate v2.1.

I am using Fluent v1 and NHibernate v2.1.

我也尝试将我的 DateTime 映射到时间戳,但由于插入失败,甚至无法使映射正常工作:

I have also tried mapping my DateTime to a TimeStamp but couldn't even get the mapping working as the insert fails stating:

无法在时间戳列中插入显式值.使用带有列列表的 INSERT 排除时间戳列,或将 DEFAULT 插入时间戳列.

Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column.

有谁知道如何让 SchemeExport 与 datetime2 一起工作,或者如何让时间戳映射适用于 datetime 属性?

Does anyone know either how to get the SchemeExport working with a datetime2 OR how to get timestamp mapping working for a datetime property?

推荐答案

实际上 NHibernate 参考指出 DateTime nhibernate 类型会将 .NET DateTime 存储为在第二级截断的 SQL 日期时间(无毫秒粒度)

Actually the NHibernate reference states that the DateTime nhibernate type will store the .NET DateTime as an SQL datetime truncated at the second level (no millisecond granularity)

因此,它提供了 Timestamp NHibernate 类型(映射中的type="Timestamp"),它将存储 .NET DateTime 作为没有截断的 SQL datetime.请注意,SQL timestamp 数据类型不需要,如果一张表中有多个 timestamp 列,实际上会中断.因此,区分 NHibernate 映射中的 sql-typetype 属性非常重要.

As such it provides the Timestamp NHibernate type (type="Timestamp" in the mapping) which will store a .NET DateTime as an SQL datetime without truncation. Note here that an SQL timestamp datatype is not needed and will infact break if you have more than one timestamp column in one table. It's thus important to differentiate between the sql-type and type attributes in the NHibernate mapping.

此外,请注意,如果您正在使用过滤器,则同样的规则适用于过滤器定义:如果您指定一个 DateTime 参数,则该参数的值将被截断而不是毫秒.

Additionally, note that if you are working with filters, the same rule applies at the filter definition: If you specify a DateTime parameter, the parameter's value will be truncated without milliseconds.

查看 第 5.2.2 章.基本值类型表 5.3 System.ValueType 映射类型.

这篇关于NHibernate 中的 DateTime 精度和 NHibernate SchemeExport 中对 DateTime2 的支持的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 02:52