2009-07-27 12 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として保存します(ティックを保存しますが、この解像度は必要ありませんが、時間帯には時間帯を保存しないでください)。の時間帯オフセットはです。 !TimeSpanは、そのままの状態でビルドされています。)

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) 

私は2つの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

Ok、fair enough ...私はそれまでのところです。しかし、あなたの 'dt'インスタンスはドメインモデルにどのように戻ってきますか? – codekaizen

+0

dt =コンポーネント。DateTimeにキャストされました。どこでも((DateTime)コンポーネントで)置き換えることができます。コンポーネントは実際にドメインモデルに返されたものです。 – anonymous

+0

この資料のドキュメントがあるかどうかはわかりません。私はそれを覚えていないし、私のコードで文脈を見なければならなかった。私は、通常NHibernateで提供されている例を見なければならないと思っています(私は思っていますか?)そしてそれから学びます(そして、一度やったらそれを忘れてしまいます!) – anonymous

2

マップするタイプがICompositeUserTypeで不変の場合、SetPropertyValue()は何もしないか、例外をスローする必要があります.nhibernateは呼び出さないでください。

関連する問題