2009-07-27 35 views
9

我有一個域模型對象,它具有System.DateTimeOffset類型的屬性。我使用的數據庫本身不支持這種類型,所以我打算使用'datetime'類型和'smallint'類型之一來存儲它。使用具有值類型的NHibernate ICompositeUserType

我已經挖掘瞭如何使用NHibernate組件映射這個,並發現它可以使用ICompositeUserType實例工作。但是,在實現接口後,我遇到了名爲「SetPropertyValue」的方法,該方法表面上在類型中設置了一個屬性。由於DateTimeOffset是一個System.ValueType,只是設置這樣的屬性將不起作用,因爲它是不可變的(至少,沒有使用反射或不安全的代碼,我想避免)。由於SetPropertyValue上的實例參數不是'ref',因此如何在NHibernate中使用ValueType實例作爲組件?

回答

6

通過在IsMutable中返回false來使用戶類型不可變,並且僅在SetPropertyValue中引發異常。

我有類似的東西,但有一個自己的數據類型而不是DateTimeOffset。我只是爲你調整了代碼。它將日期存儲爲UTC時間,並將偏移量存儲爲TimeSpan(存儲Ticks。當然,您不需要此分辨率,但是,您不應該存儲整個小時的時區,有時區偏移小時小數點! !是在一個開箱即用的作品。)

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
public void SetPropertyValue(object component, int property, object value) 

我有兩個int字段實現DateTime的代碼。

代碼本質上是一個開關屬性(0是日期,1是時間,在我的情況),並在每個case語句結束時,組件對象被重新分配一個新的DateTime實例。

屬性= 0(日期):

// 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); 

屬性= 1(時間):

// 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); 

不知道這是否是好/壞,但對我的作品(又名我有沒有問題改變什麼組件指向,參考或不)。

+0

好吧,公平的......我追隨到目前爲止。但是,你的'dt'實例如何回到域模型? – codekaizen 2009-07-27 17:49:31

2

這是我的理解,如果你映射的類型和ICompositeUserType是不可變的,SetPropertyValue()應該什麼都不做,甚至拋出一個異常,因爲nhibernate不應該調用它。

相關問題