3

Nhibernate を使用して DB に永続化したい TimeSpan プロパティがあります。Mysql の列の種類は時間です。その辺り読んだ

CustomType("TimeAsTimeSpan")

問題を解決する必要がありますが、そうではありません。

session.Save(オブジェクト)

次の MySqlException が発生します

MySqlTimeSpan エラーでシリアル化できるのは TimeSpan オブジェクトのみです

永続化しようとしているタイムスタンプ プロパティは、有効なタイムスタンプです。何か提案はありますか?

4

2 に答える 2

2

これは Hibernate のバグです。TimeAsTimeSpan クラスのクローンを作成することで、これを修正することができました。

利用方法:

CustomType(typeof(TimeAsTimeSpanTypeClone));

クラス:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using NHibernate.Engine;
using NHibernate.SqlTypes;
using NHibernate.Type;

namespace DataAccess.NhibernateFixes
{
    /// <summary>
    /// Clone of the Nhibernate class: NHibernate.Type.TimeAsTimeSpanType
    /// This one actually works though...
    /// </summary>
    [Serializable]
    public class TimeAsTimeSpanTypeClone : PrimitiveType, IVersionType, IType, ICacheAssembler
    {
        private static readonly DateTime BaseDateValue = new DateTime(1753, 1, 1);

        public override string Name
        {
            get
            {
                return "TimeAsTimeSpan";
            }
        }

        public override System.Type ReturnedClass
        {
            get
            {
                return typeof(TimeSpan);
            }
        }

        public IComparer Comparator
        {
            get
            {
                return (IComparer)Comparer<TimeSpan>.Default;
            }
        }

        public override System.Type PrimitiveClass
        {
            get
            {
                return typeof(TimeSpan);
            }
        }

        public override object DefaultValue
        {
            get
            {
                return (object)TimeSpan.Zero;
            }
        }

        static TimeAsTimeSpanTypeClone()
        {
        }

        public TimeAsTimeSpanTypeClone()
            : base(SqlTypeFactory.Time)
        {
        }

        public override object Get(IDataReader rs, int index)
        {
            try
            {
                object obj = rs[index];
                if (obj is TimeSpan)
                    return (object)(TimeSpan)obj;
                else
                    return (object)((DateTime)obj).TimeOfDay;
            }
            catch (Exception ex)
            {
                throw new FormatException(string.Format("Input string '{0}' was not in the correct format.", rs[index]), ex);
            }
        }

        public override object Get(IDataReader rs, string name)
        {
            try
            {
                object obj = rs[name];
                if (obj is TimeSpan)
                    return (object)(TimeSpan)obj;
                else
                    return (object)((DateTime)obj).TimeOfDay;
            }
            catch (Exception ex)
            {
                throw new FormatException(string.Format("Input string '{0}' was not in the correct format.", rs[name]), ex);
            }
        }

        public override void Set(IDbCommand st, object value, int index)
        {
            DateTime dateTime = TimeAsTimeSpanTypeClone.BaseDateValue.AddTicks(((TimeSpan)value).Ticks);
            ((IDataParameter)st.Parameters[index]).Value = (object)dateTime.TimeOfDay; // <<<<  fix here. Added ".TimeOfDay"
        }

        public override string ToString(object val)
        {
            return ((TimeSpan)val).Ticks.ToString();
        }

        public object Next(object current, ISessionImplementor session)
        {
            return this.Seed(session);
        }

        public virtual object Seed(ISessionImplementor session)
        {
            return (object)new TimeSpan(DateTime.Now.Ticks);
        }

        public object StringToObject(string xml)
        {
            return (object)TimeSpan.Parse(xml);
        }

        public override object FromStringValue(string xml)
        {
            return (object)TimeSpan.Parse(xml);
        }

        public override string ObjectToSQLString(object value, NHibernate.Dialect.Dialect dialect)
        {
            return (string)(object)'\'' + (object)((TimeSpan)value).Ticks.ToString() + (string)(object)'\'';
        }
    }
}
于 2014-09-25T14:45:58.967 に答える
0

誰も私の質問に答えず、さまざまなアプローチを試しても結果が得られなかったので、回避策を講じることにしました。varchar 列タイプ (時間タイプではなくなりました) に挿入するときに、タイムスタンプ オブジェクトを文字列に変換し、キャストします。 DB からの読み取り時に文字列をタイムスタンプ オブジェクトに戻します。念のため、その変換のコードを次に示します。

DateTime.Parse(startTimebtn.Text).TimeOfDay.ToString();

于 2012-07-09T13:13:45.940 に答える