重新水化fluent nhibernate将日期时间配置为Utc种类,而不是未指定

重新水化fluent nhibernate将日期时间配置为Utc种类,而不是未指定,nhibernate,datetime,utc,Nhibernate,Datetime,Utc,在fluent nhibernate中是否有方法映射日期时间,以将我的实体与日期时间重新水化。种类设置为Utc而不是未指定?我目前坚持使用Utc的日期时间,但返回的日期时间总是不确定的,这会耽误我的时间。这不是fluent特有的,而是NHibernate映射的基础。我们使用拦截器来指定类型。它类似于列出几个备选方案的方法。还有一种方法用于本机处理UtcDateTime和LocalDateTime。我鼓励你投赞成票 public class InterceptorBase : EmptyInter

在fluent nhibernate中是否有方法映射日期时间,以将我的实体与日期时间重新水化。种类设置为Utc而不是未指定?我目前坚持使用Utc的日期时间,但返回的日期时间总是不确定的,这会耽误我的时间。

这不是fluent特有的,而是NHibernate映射的基础。我们使用拦截器来指定类型。它类似于列出几个备选方案的方法。还有一种方法用于本机处理UtcDateTime和LocalDateTime。我鼓励你投赞成票

public class InterceptorBase : EmptyInterceptor
{
    public override bool OnLoad(object entity, object id, object[] state,
        string[] propertyNames, IType[] types)
    {
        ConvertDatabaseDateTimeToUtc(state, types);
        return true;
    }

    private void ConvertDatabaseDateTimeToUtc(object[] state, IList<IType> types)
    {
        for (int i = 0; i < types.Count; i++)
        {
            if (types[i].ReturnedClass != typeof(DateTime))
                continue;

            DateTime? dateTime = state[i] as DateTime?;

            if (!dateTime.HasValue)
                continue;

            if (dateTime.Value.Kind != DateTimeKind.Unspecified)
                continue;

            state[i] = DateTime.SpecifyKind(dateTime.Value, DateTimeKind.Utc);
        }
    }
}
公共类拦截器数据库:EmptyInterceptor
{
public override bool OnLoad(对象实体、对象id、对象[]状态、,
字符串[]属性名称,IType[]类型)
{
ConvertDatabaseDateTimeToUtc(状态、类型);
返回true;
}
私有void ConvertDatabaseDateTimeToUtc(对象[]状态,IList类型)
{
for(int i=0;i
从Nhibernate 3.0开始,使用FluentNHibernate,您可以执行以下操作:

Map(x => x.EntryDate).CustomType<UtcDateTimeType>();
Map(x=>x.EntryDate).CustomType();

不再需要使用拦截器。

由于@DPeden的回答,@Ricardo_Stuven的评论似乎有点混乱,我想我应该构建这个示例:

具有:

Map(x => x.EntryDate).CustomType<LocalDateTimeType>();
也就是说,它从不调用
.ToLocalTime()
,无论您传入或从中取出什么,都假定它代表localtime,但它不是强制的,它不知道开发人员是否会正确使用DateTimeKind


类似地,
UtcDateTimeType
从不调用
.ToUniversalTime()

我想补充一点,您需要在使用该对象之前将其传递到NHibernate会话中。返回factory.OpenSession();更改为返回factory.OpenSession(新的InterceptorBase());引用的链接不再有效,但内容仍然可以在此处找到:我刚刚发现这种方法不适用于组件上的DateTime属性:-(.建议的链接已断开,新链接:在v3.0.0.Alpha2A中,修补程序的状态为
fixed
。注意:
UtcDateTimeType
强制DateTimeKind为Utc。如果保存本地时间,例如13:30 Utc-3,则它将加载时间为13:30 Utc(无偏移)。我建议使用
ToUniversalTime()
手动将所有本地时间转换为Utc,或实现“
CustomUtcDateTimeType
”自动管理此案例。是否可以为所有日期时间注册全局自定义类型?如果不可以,如果有人忘记使用自定义类型,我如何进行单元测试?此解决方案似乎给我带来了一些麻烦。假设我的本地时间是13:30 GMT+1。当使用此类型存储在数据库中时,它正确地存储为12.30 UTC。当我重新注册时从数据库中检索此日期我得到的日期是UTC 13.30。如果这是由WebAPI序列化的,则它被序列化为13.30Z,因此当我在客户端代码中对其进行本地化时,日期变为14.30 GMT+1。有什么方法可以解决此问题吗?我怀疑我之前的评论中描述的行为是特定于数据库的。我最初使用SQLite,就像我在原型设计中经常做的那样,但更改为SQL Server会使这种奇怪的行为消失。当我在单元测试期间在内存中使用SQLite时,这仍然是一个问题。@impro如果在连接字符串中放入DateTimeFormat=Ticks,它将起作用。但是,这会将不好的部分移到SQLite数据库中,因为所有日期时间都将保存为Ticks。如果仅将sqlite用于单元测试,这就足够了。
Map(x => x._hiddenEntryDate).Column("EntryDate");
Ignore(x => x.EntryDate);

///...

public class MyEntity
{
    protected virtual DateTime _hiddenEntryDate { get; set; }
    public DateTime EntryDate
    {
        get
        {
            return DateTime.SpecifyKind(_hiddenEntryDate, DateTimeKind.Local);
        }
        set
        {
            _hiddenCreated = DateTime.SpecifyKind(value, DateTimeKind.Local);
        }
    }
}