2011-09-15 12 views
4

私は仲間に挑戦するほどの質問は昨日DBAによって提出されました。永続化するオブジェクトの1つにTimeSpanというプロパティがあります。はい、オブジェクトの開始と終了のDateTimeプロパティから値を推測することができますが、DBAはこの値がデータベーステーブルに保存されていることを確信しています。OracleのINTERVAL DAY TO SECONDデータ型のためのNHibernateマッピング

したがって、値を保持するためにDBAによって選択されるOracleデータ型は、INTERVAL DAY(2)TO SECOND(6)です。

Oracle.DataAccessの対応する型はOracleDbType.InvervalDSですが、NHibernateでそれをどのようにマップするかについては何も見つかりませんでした。

は、我々は

class Program 
    { 
     static void Main(string[] args) 
     { 
      SomeTimeSpanTestClass spanClass = new SomeTimeSpanTestClass(); 

      DateTime start = DateTime.Now; 
      DateTime end = DateTime.Now.AddMinutes(75); 
      spanClass.ActualTimeSpan = end.Subtract(start); 

      Console.WriteLine(spanClass.TimeSpanTest);   

     } 
    } 

として非常にnoddyでテストが明らかにこのコードがどのような方法でリファクタリングされていない

<property name="TimeSpanTest" column="TIMESPAN_TEST"/> 

としてマッピングして、このソリューション

public class SomeTimeSpanTestClass 
    { 
     public virtual string TimeSpanTest { get; protected set; } 
     public virtual TimeSpan ActualTimeSpan 
     { 
      get 
      { 
       // Need to do some formatting of TimeSpanTest before it can be parsed 
       return TimeSpan.Parse(TimeSpanTest); 
      } 
      set 
      { 
       TimeSpanTest = string.Format("{0}{1} {2}:{3}:{4}.{5}", 
        value.ToString().Contains('-') ? "-" : "+", 
        value.Days.ToString().Contains('-') ? value.Days.ToString().Substring(1).PadLeft(2, '0') : value.Days.ToString().PadLeft(2, '0'), 
        value.Hours.ToString().Contains('-') ? value.Hours.ToString().Substring(1).PadLeft(2, '0') : value.Hours.ToString().PadLeft(2, '0'), 
        value.Minutes.ToString().Contains('-') ? value.Minutes.ToString().Substring(1).PadLeft(2, '0') : value.Minutes.ToString().PadLeft(2, '0'), 
        value.Seconds.ToString().Contains('-') ? value.Seconds.ToString().Substring(1).PadLeft(2, '0') : value.Seconds.ToString().PadLeft(2, '0'), 
        value.Milliseconds.ToString().Contains('-') ? value.Milliseconds.ToString().Substring(1).PadLeft(6, '0') : value.Milliseconds.ToString().PadLeft(6, '0') 
       ); 
      } 
     } 
    } 

になってしまいましたしかし、このテストの目的のためには、とにかく簡単です。

データベースの値は、基本的には "+01 01:15:03.000874"のようになります。値が負の場合、文字列の先頭にA記号も有効です。ここで注意すべき重要な点は、値が負の場合、TimeSpanオブジェクトの各部分は、単独で見たときに負の値をとるため、それほど美しくない "value.Days.ToString()。Contains( ' - ')" in Format()メソッドの各セクション

私たちのテストでは、NHibernate経由でINTERVAL DAY(2)〜SECOND(6)として定義されたデータベース列にTimeSpan値を保存して取得できます。

もっと良い方法の前に誰かがこれをやったことがあれば、私は非常に興味があると思います。 Oracle型を結ぶないため

謝罪私は...

+0

を追加しましたTimespanプロパティをマップするUsertype。次に、TimeSpanTestと変換コードがオブジェクトに必要ありません。私は必要に応じて実装することができます – Firo

+0

してください。私が言ったように、これはそれが私たちの最初の亀裂であり、より良い方法があれば、それをやる方法を知りたいです。 –

答えて

2
public virtual TimeSpan ActualTimeSpan { get; set; } 



class TimeSpanUserType : ImmutableUserType 
{ 
    public override object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     // Need to do some formatting of TimeSpanTest before it can be parsed 
     return TimeSpan.Parse((string)rs[names[0]]); 
    } 

    public override void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     var timespan = (TimeSpan)value; 
     var duration = timespan.Duration(); 
     var timeSpanstring = string.Format("{0}{1} {2}:{3}:{4}.{5}", 
      (timespan.Ticks < 0) ? "-" : "+", 
      duration.Days.ToString().PadLeft(2, '0'), 
      duration.Hours.ToString().PadLeft(2, '0'), 
      duration.Minutes.ToString().PadLeft(2, '0'), 
      duration.Seconds.ToString().PadLeft(2, '0'), 
      duration.Milliseconds.ToString().PadLeft(6, '0')); 

     NHibernateUtil.String.NullSafeSet(cmd, timeSpanstring, index); 
    } 

    public override Type ReturnedType 
    { 
     get { return typeof(TimeSpan); } 
    } 

    public override SqlType[] SqlTypes 
    { 
     get { return new[] { SqlTypeFactory.GetString(8) }; } 
    } 
} 

<property name="ActualTimeSpan" column="TIMESPAN_TEST" type="TimeSpanUserType"/> 

編集を許可されていないよので、それは私の最初の投稿です:あなたもNH-で行くことができimmutableUserType

public abstract class ImmutableUserType : IUserType 
{ 
    public new virtual bool Equals(object x, object y) 
    { 
     return object.Equals(x, y); 
    } 

    public virtual int GetHashCode(object x) 
    { 
     return (x == null) ? 0 : x.GetHashCode(); 
    } 

    public override bool IsMutable 
    { 
     get { return false; } 
    } 

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

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

    public override object Assemble(object cached, object owner) 
    { 
     return cached; 
    } 

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

    public abstract object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner); 

    public abstract void NullSafeSet(System.Data.IDbCommand cmd, object value, int index); 
    public abstract Type ReturnedType { get; } 

    public abstract SqlType[] SqlTypes { get; } 
} 
+0

返事をありがとう。私はあなたがどのようにIDataReaderとIDbCommand NHibernateとのインターフェイスを使用しているか分かりません。 –

+0

私はその質問を理解していません。コードNHに示されているように、それらはパラメータとして与えられ、値を挿入/取得するだけです – Firo

+1

ありがとうございます@フィロは私のために働いた – saggu

関連する問題