首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >NHibernate中的DateTime精度和NHibernate SchemeExport中对DateTime2的支持

NHibernate中的DateTime精度和NHibernate SchemeExport中对DateTime2的支持
EN

Stack Overflow用户
提问于 2010-01-09 22:23:14
回答 5查看 17K关注 0票数 25

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

代码语言:javascript
运行
复制
public class Foo
{    
public virtual int Id { get; set; }    
public virtual datetime CreatedDateTime { get; set; }    
}

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

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

代码语言:javascript
运行
复制
public class FooMap : IAutoMappingOverride<Foo>
{
    public void Override(AutoMapping<Foo> mapping)
    {
        mapping.Map(f => f.CreatedDateTime).CustomType("datetime2");     
    }
}

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

但是,一次传递会导致另一次失败:我的检查模式导出的测试现在失败了,错误如下:

代码语言:javascript
运行
复制
System.ArgumentException : Dialect does not support DbType.DateTime2
Parameter name: typecode

堆栈跟踪为:

代码语言:javascript
运行
复制
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方法。

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

我还尝试将我的DateTime映射到TimeStamp,但由于插入失败,我甚至无法使映射工作,声明如下:

无法在时间戳列中插入显式值。将INSERT与列列表一起使用可排除时间戳列,或在时间戳列中插入DEFAULT

有没有人知道如何让SchemeExport与datetime2一起工作,或者如何让时间戳映射为datetime属性工作?

EN

回答 5

Stack Overflow用户

发布于 2010-02-23 19:56:44

实际上,NHibernate引用声明DateTime nhibernate类型将把.NET DateTime存储为在第二级截断的SQL datetime (无毫秒粒度)。

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

此外,请注意,如果您正在使用筛选器,则相同的规则也适用于筛选器定义:如果您指定了DateTime参数,则该参数的值将被截断,而不会有毫秒。

看看chapter 5.2.2. Basic value typesTable 5.3 System.ValueType Mapping Types

票数 33
EN

Stack Overflow用户

发布于 2015-06-10 18:00:55

对于希望实际保留日期的纳秒部分的任何人,您必须使用DateTime2作为sql-column类型以及Nhibernate DateTime2类型。

下面是我的设置约定(使用fluent)

代码语言:javascript
运行
复制
public class DateTimeConvention : IPropertyConvention, IPropertyConventionAcceptance
{

    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Type == typeof(DateTime) || x.Type == typeof(DateTime?));
    }
    public void Apply(IPropertyInstance instance)
    {
        instance.CustomSqlType("DateTime2"); //specify that the sql column is DateTime2
        instance.CustomType("DateTime2"); //set the nhib type as well
    }
}

并激活约定:

代码语言:javascript
运行
复制
 var v = Fluently.Configure()
         .Database(MsSqlConfiguration.MsSql2008
         .ConnectionString(d => d.FromConnectionStringWithKey("connstring"))
         .ShowSql())
         .Mappings(m => m.FluentMappings.AddFromAssemblyOf<IRepository>()
         .Conventions.AddFromAssemblyOf<IRepository>()) //this adds your convention
         .BuildSessionFactory();

使用它,您可以在存储日期时间时保持纳秒。

票数 6
EN

Stack Overflow用户

发布于 2010-01-09 22:40:30

我在业务类的CreatedDate审计字段中遇到了同样的问题。我通过使用实用程序方法中的值设置时间来解决这个问题。希望这能有所帮助。

代码语言:javascript
运行
复制
     /// <summary>
    /// Return a DateTime with millisecond resolution to be used as the timestamp. This is needed so that DateTime of an existing instance
    /// will equal one that has been persisted and returned from the database. Without this, the times differ due to different resolutions.
    /// </summary>
    /// <returns></returns>
    private DateTime GetTime()
    {
        var now = DateTime.Now;
        var ts = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond, DateTimeKind.Local);
        return ts;
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2033630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档