Using NHibernate ICompositeUserType with a value type

后端 未结 3 2021
名媛妹妹
名媛妹妹 2021-01-12 00:15

I have a domain model object which has properties of type System.DateTimeOffset. I\'m using a database which doesn\'t support this type natively, so I\'m planning to store i

相关标签:
3条回答
  • 2021-01-12 00:55

    It's my understanding that if the type you're mapping with and ICompositeUserType is immutable, SetPropertyValue() should do nothing at all, or even throw an exception, since nhibernate shouldn't be calling it.

    0 讨论(0)
  • 2021-01-12 00:55
    public void SetPropertyValue(object component, int property, object value)
    

    I have code that implements DateTime from two int fields.

    The code essentially is a switch on property (0 being date, 1 being time, in my case) and at the end of each case statement the component object is reassigned a new DateTime instance.

    property = 0 (Date):

    // code to calculate year, month, day from object value
    DateTime dt = (DateTime)component;
    dt = new DateTime(year, month, day, dt.Hour, dt.Minute, dt.Second);
    

    property = 1 (Time):

    // code to calculate hours, minutes, seconds from object value
    DateTime dt = (DateTime)component;
    dt = new DateTime(dt.Year, dt.Month, dt.Day, hours, minutes, seconds);
    

    No idea if this is good / bad, but it works for me (aka I have no problem changing what component points to, ref or not).

    0 讨论(0)
  • 2021-01-12 01:06

    Make the user type immutable by returning false in IsMutable and just throw an exception in SetPropertyValue.

    I have something similar, but with an own datatype instead of DateTimeOffset. I just adapted the code for you. It stores the date as UTC time and the offset as TimeSpan (stores Ticks. Of course you don't need this resolution. But, you should not store whole hours for time zones, there are time zones offsets with fractions of hours!! And TimeSpan is build in an works out of the box.)

    public class DateTimeOffsetUserType : ICompositeUserType
    {
        public bool IsMutable
        {
            get { return false; }
        }
    
        public void SetPropertyValue(object component, int property, object value)
        {
            throw new InvalidOperationException("Immutable, SetPropertyValue is not allowed");
        }
    
        public object NullSafeGet(System.Data.IDataReader dr, string[] names, NHibernate.Engine.ISessionImplementor session, object owner)
        {
            if (dr == null)
            {
                return null;
            }
    
            DateTime? utcTime;
            TimeSpan? offset;
    
            utcTime = (DateTime?)PropertyTypes[0].NullSafeGet(dr, names[0], session, owner);
            offset = (TimeSpan?)PropertyTypes[1].NullSafeGet(dr, names[1], session, owner);
    
            if (utcTime == null || offset == null) return null;
            return new DateTimeOffset(utcTime.Value, offset.Value);
        }
    
        public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index, NHibernate.Engine.ISessionImplementor session)
        {
            if (value == null)
            {
                NHibernateUtil.Timestamp.NullSafeSet(cmd, null, index);
                NHibernateUtil.TimeSpan.NullSafeSet(cmd, null, index + 1);
            }
            else
            {
                DateTimeOffset dateTimeOffset = (DateTimeOffset)value;
    
                PropertyTypes[0].NullSafeSet(cmd, dateTimeOffset.UtcDateTime, index, session);
                PropertyTypes[1].NullSafeSet(cmd, dateTimeOffset.Offset, index + 1, session);
            }
    
        }
    
        // other methods
    
    0 讨论(0)
提交回复
热议问题