问题
Is there a way in fluent nhibernate to map a DateTime to rehydrate my entity with DateTime.Kind set to Utc rather than unspecified? I'm currently persisting a DateTime that is Utc, but the Kind coming back is always Unspecified, throwing off my time.
回答1:
This isn't specific to fluent, but is fundamental to the NHibernate mapping. We use an interceptor to specify the Kind. It is similar to the approach in this blog post which lists a couple alternatives. There is also a proposed patch (NH-1135) for handling UtcDateTime and LocalDateTime natively. I'd encourage you to vote for it.
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);
}
}
}
回答2:
As of Nhibernate 3.0, using FluentNHibernate, you can do the following:
Map(x => x.EntryDate).CustomType<UtcDateTimeType>();
No need to use interceptors anymore.
回答3:
Due to @DPeden's answer, and the comment by @Ricardo_Stuven seeming to have slight confusion, I thought I would construct this example:
Having:
Map(x => x.EntryDate).CustomType<LocalDateTimeType>();
Is the same as having: (This code is meant to be illustrative, it is NOT an example to follow)
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);
}
}
}
Namely, it NEVER calls .ToLocalTime()
, whatever you pass into it, or get out of it, is assumed to represent localtime, it is not enforced to be, it does not recognize that the developer would ever use DateTimeKind correctly.
Similarly UtcDateTimeType
never calls .ToUniversalTime()
来源:https://stackoverflow.com/questions/1547133/rehydrating-fluent-nhibernate-configured-datetime-as-kind-utc-rather-than-unspec