开发者

How to map a oracle decimal date into a datetime property with Nhibernate

开发者 https://www.devze.com 2023-02-15 06:43 出处:网络
I am working with an oracle legacy database. All the dates are saved in decimal fields with the following format YY开发者_C百科YYMMDD.

I am working with an oracle legacy database.

All the dates are saved in decimal fields with the following format YY开发者_C百科YYMMDD.

Is there a way to transform this kind of type in a datetime (c#), maybe in the mapping file?


Just write a custom IEnhancedUserType that converts to and from the string representation.

That way it will be transparent to your application.


Recently I faced with the same problem and ended up with writing the following method:

    public static DateTime? ConvertFromOracleDate(object oracleDate)
    {
        if (oracleDate == null)
            throw new ArgumentNullException("oracleDate");

        if (!(oracleDate is string))
            throw new ArgumentException("oracleDate");  

        var sDate = (string) oracleDate;

        if (sDate.Equals(String.Empty))
            return null;

        if (sDate.Length != 8)
            throw new ArgumentOutOfRangeException("oracleDate");

        sDate = sDate.Insert(6, "/");
        sDate = sDate.Insert(4, "/");
        var ci = new CultureInfo("en-US");

        return Convert.ToDateTime(sDate, ci);
    }

Hope this helps.


Ended up writing a custom IUserType.
For those who are interested here is the code. I haven't tried the writing process cause my table is read-only at the moment:

public class DecimalToDateUserType : IUserType
{
    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        int? result = (int)NHibernateUtil.Int32.NullSafeGet(rs, names[0]);
        if ((result != null)&&(result.Value>0))
        {
            var sDate = result.Value.ToString();
            sDate = sDate.Insert(6, "/").Insert(4, "/");
            var ci = new CultureInfo("en-US");

            return Convert.ToDateTime(sDate, ci);
        }
        return (DateTime.MinValue);
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        if (value == null)
        {
            NHibernateUtil.Int32.NullSafeSet(cmd, null, index);
            return;
        }

        if ((DateTime)value == DateTime.MinValue)
        {
            value = 0;
            NHibernateUtil.Int32.NullSafeSet(cmd, value, index);
            return;
        }

        int convertedValue = 0;
        int.TryParse(((DateTime)value).ToString("yyyyMMdd"), out convertedValue);

        value = convertedValue;

        NHibernateUtil.Int32.NullSafeSet(cmd, value, index);
    }

    public object DeepCopy(object value)
    {
        if (value == null) return null;
        return (value);
    }

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

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

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

    public SqlType[] SqlTypes
    {
        get
        {
            SqlType[] types = new SqlType[1];
            types[0] = new SqlType(DbType.Decimal);
            return types;
        }
    }

    public Type ReturnedType
    {
        get { return typeof(DateTime); }
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public new bool Equals(object x, object y)
    {
        if (x == null || y == null) return false;
        return x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }
}


You can also do the transformation in your SQL query using

TO_DATE(TO_CHAR(semi_date_field),'yyyymmdd'))

Then you'll select a column with Oracle-datatype DATE. C# will undoubtedly treat those as datetimes.

Regards,
Rob.

0

精彩评论

暂无评论...
验证码 换一张
取 消