j3f*_*ffb 23 nhibernate datetime timestamp fluent-nhibernate granularity
然后我使用Fluent NHibernate及其自动化功能来映射以下简化的POCO类:
public class Foo
{
public virtual int Id { get; set; }
public virtual datetime CreatedDateTime { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
默认情况下,CreatedDateTime字段将映射到SQL DateTime.但是,如果我进行测试以检查实体是否正确创建,则会失败.这是因为DateTime字段的精度不会保留到SQL数据库.我强调这背后的原因是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");
}
}
Run Code Online (Sandbox Code Playgroud)
我知道这个映射使得NHibernate将CreatedDateTime持久化为datetime2的SQL类型,它可以存储.NET DateTime可以的完整精度.这是一种享受,现在测试通过了.
然而,一次传递另一个失败:我检查架构导出的测试现在失败,出现以下错误:
System.ArgumentException : Dialect does not support DbType.DateTime2
Parameter name: typecode
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪:
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)
Run Code Online (Sandbox Code Playgroud)
该代码使用NHibernate.Tool.hbm2ddl.SchemaExport对象来调用Execute方法.
我正在使用Fluent v1和NHibernate v2.1.
我也尝试将我映射DateTime到TimeStamp但是甚至无法使映射工作,因为插入失败说明:
无法将显式值插入时间戳列.INSERT与列列表一起使用以排除时间戳列,或将其DEFAULT插入到时间戳列中.
有没有人知道如何让SchemeExport使用datetime2OR如何获取datetime属性的时间戳映射?
Jag*_*uar 32
实际上NHibernate引用声明DateTime nhibernate类型将.NET DateTime存储为在第二级截断的SQL日期时间(没有毫秒粒度)
因此,它提供了TimestampNHibernate类型(type="Timestamp"在映射中),它将.NET DateTime作为SQL 存储datetime而不会截断.这里注意,一个SQL timestamp的数据类型并不需要,如果你有一个以上的将INFACT突破timestamp在一个表中的列.它的区分是这样的重要sql-type,并type在NHibernate的映射属性.
此外,请注意,如果使用过滤器,则在过滤器定义中应用相同的规则:如果指定DateTime参数,则参数的值将被截断而不会超过毫秒.
查看第5.2.2章.基本值类型,表5.3 System.ValueType映射类型.
对于任何想要实际保留日期的纳秒部分的人,您必须使用DateTime2作为sql-column类型以及Nhibernate DateTime2类型.
这是我设置它的惯例(使用流利)
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
}
}
Run Code Online (Sandbox Code Playgroud)
并激活惯例:
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();
Run Code Online (Sandbox Code Playgroud)
使用此功能,您可以在存储日期时保持纳秒.
我在业务课程上的 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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15674 次 |
| 最近记录: |