Question

I use Fluent NHibernate to access an IBM DB2400 iSeries database. This, by and large, works fine. I have had to create several custom data types, because not every iSeries data type maps exactly to something in C# .NET (and also because the database designers sometimes decided to store dates in string or int fields, but that's neither here nor there). These also, by and large, work fine.

My problem is with the custom type I made to handle the TIME data type on the iSeries. I can read from it just fine and convert what I get to a DateTime object. I can even write to it... sometimes. Any time after 10 am works fine, it's 12:00-09:59 that's the problem.

After extensive testing, I figured out that Fluent NHibernate treats the TIME data type as an int, and the value written to the field has to be in HH0mm0ss format to be detected correctly. I don't know why it needs those zeroes, but it does. It skips those digits, so if you don't use them, an input of 122153 gets read as 12:15:30, and 122538 would get rejected as bad input because 12:53:80 is not a valid time.

All that I can deal with. The problem is that, since Fluent NHibernate treats TIME as an int, it discards any leading zeroes. If it's 5:17 and I pass it 05017023, it reads that as 50:70:30. This is, obviously, a problem, and it's one that I can't seem to find a way around. If anyone's encountered this before or has any ideas, I'm all ears.

Here's the relevant code from the custom data type:

public void NullSafeSet(IDbCommand cmd, object value, int index)
{
    if (value == null)
    {
        NHibernateUtil.String.NullSafeSet(cmd, null, index);
        return;
    }
    value = ((DateTime)value).ToString("HH0mm0ss"); //no I don't know why we need those zeroes there, but we do. Because ISeries I guess
    NHibernateUtil.String.NullSafeSet(cmd, value, index); 
}

It uses string rather than ints because Fluent NHibernate tries to convert whatever you give it in "value" to an int automatically, so I just don't need to bother with that step myself.

And here's a map from one of the tables that has a TIME type field:

public class PPFP01067Map : ClassMap<PPFP01067>
{
        public PPFP01067Map()
        {
            Table("PPFP01067");
            Id(x => x.PMACCT);
            Map(x => x.PMHOME);
            Map(x => x.PMCELL);
            Map(x => x.PMTEXT).Length(1);
            Map(x => x.PMWORK);
            Map(x => x.PMPREF).Length(1);
            Map(x => x.PMDATE).CustomType<Db2DateType>();
            Map(x => x.PMTIME).CustomType<Db2TimeType>();
            Map(x => x.PMAUTH).Length(5);
        }
}
Was it helpful?

Solution

I found the answer. I was looking in the wrong place; the key clue was that the code thought TIME was an int field. I looked a bit deeper in the custom type code and found this:

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

All I had to do was change that to DbType.DateTime and it works fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top