然后,我使用Fluent NHibernate及其自动映射功能来映射以下简化的POCO类:
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对象添加了以下映射:
public class FooMap : IAutoMappingOverride<Foo>
{
public void Override(AutoMapping<Foo> mapping)
{
mapping.Map(f => f.CreatedDateTime).CustomType("datetime2");
}
}据我所知,这种映射使NHibernate将CreatedDateTime持久化为SQL类型的datetime2,它可以存储.NET DateTime所能存储的全部精度。这很有效,现在测试通过了。
但是,一次传递会导致另一次失败:我的检查模式导出的测试现在失败了,错误如下:
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方法。
我使用的是Fluent v1和NHibernate v2.1。
我还尝试将我的DateTime映射到TimeStamp,但由于插入失败,我甚至无法使映射工作,声明如下:
无法在时间戳列中插入显式值。将INSERT与列列表一起使用可排除时间戳列,或在时间戳列中插入DEFAULT。
有没有人知道如何让SchemeExport与datetime2一起工作,或者如何让时间戳映射为datetime属性工作?
发布于 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-type和type属性非常重要。
此外,请注意,如果您正在使用筛选器,则相同的规则也适用于筛选器定义:如果您指定了DateTime参数,则该参数的值将被截断,而不会有毫秒。
看看chapter 5.2.2. Basic value types,Table 5.3 System.ValueType Mapping Types。
发布于 2015-06-10 18:00:55
对于希望实际保留日期的纳秒部分的任何人,您必须使用DateTime2作为sql-column类型以及Nhibernate DateTime2类型。
下面是我的设置约定(使用fluent)
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
}
}并激活约定:
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();使用它,您可以在存储日期时间时保持纳秒。
发布于 2010-01-09 22:40:30
我在业务类的CreatedDate审计字段中遇到了同样的问题。我通过使用实用程序方法中的值设置时间来解决这个问题。希望这能有所帮助。
/// <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;
}https://stackoverflow.com/questions/2033630
复制相似问题