hibernatenhibernatefluent-nhibernatenhibernate-mappingiusertype

IUserType to default UTC Timestamp not persisting value


I built an IUserType class to default a UTC creation timestamp on a record. I thought I implemented it correctly, but it persists nothing to the database. Can someone tell me what I am doing wrong? The class resembles this:

public class UTCTimeStamp : IUserType
{
    public object Assemble(object cached, object owner)
    {
        return DeepCopy(cached);
    }

    public object DeepCopy(object value)
    {
        var orig = value as Nullable<DateTime>;
        if (orig == null) return null;
        var newVal = new DateTime(
            ((DateTime)orig).Ticks);
        return newVal;
    }

    public object Disassemble(object value)
    {
        return DeepCopy(value);
    }

    public bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (x == null || y == null) return false;
        return x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        if (x == null)
        {
            throw new ArgumentNullException("Argument cannot be null.");
        }
        return x.GetHashCode();
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
    {
        var timestamp = NHibernate.NHibernateUtil.DateTime.NullSafeGet(rs, names[0]);
        if (timestamp != null && timestamp is DateTime)
        {
            return (DateTime)timestamp;
        }
        return null;
    }

    public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
    {
        if (value == null || !(value is Nullable<DateTime>))
        {
            NHibernate.NHibernateUtil.DateTime.NullSafeSet(cmd, DateTime.UtcNow, index);
            return;
        }
        NHibernate.NHibernateUtil.DateTime.NullSafeSet(
            cmd, value, index);
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public Type ReturnedType
    {
        get
        {
            return typeof(Nullable<DateTime>);
        }
    }

    public NHibernate.SqlTypes.SqlType[] SqlTypes
    {
        get
        {
            return new[] { new SqlType(System.Data.DbType.DateTime) };
        }
    }
}

The mapping looks like this:

Map(x => x.CreatedTimestamp)
    .Column("CreatedTimeStamp")
    .CustomType<UTCTimeStamp>()
    .Not.Nullable();

The database is getting -infinty for the value of the record (PostgreSQL). I don't know what I am doing wrong; can someone point me in the right direction?


Solution

  • OK, the problem had nothing to do with the IUserType implementation; I was defining my POCOs as DateTime, not Nullable<DateTime>, so they were defaulting to DateTime.MinValue.

    Once I changed that, everything worked exactly as I wanted.