Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working with Time Type in Fluent Nhibernate generates exception "Unable to cast object of type 'System.DateTime' to type 'NHibernate.Type.TimeType"

I founded that NHibernate have several builtin Types that are not present in C#, but are present in some of SGBD.

Now I have following:

public class TimeSlot : EntityBase
{            
    public virtual NHibernate.Type.TimeType FromTime { get; set; }
    public virtual NHibernate.Type.TimeType ToTime { get; set; }
}

public class TimeSlotMap : ClassMap<TimeSlot>
{
    public TimeSlotMap()
    {
        Id(c => c.Id).GeneratedBy.Identity();
        Map(c => c.FromTime);
        Map(c => c.ToTime);                     
    }
}

In MSSQL this table look like in attached imageenter image description here

Now when I am trying to query this table I am getting following exception:

Unable to cast object of type 'System.DateTime' to type 'NHibernate.Type.TimeType

What I am doing wrong? And how is Fluent NHibernate working with Time Date Type?

like image 598
Nic Avatar asked Mar 19 '23 06:03

Nic


1 Answers

I would suggest, to use TimeSpan for a DB type Time

public class TimeSlot : EntityBase
{
    public virtual TimeSpan FromTime { get; set; }
    public virtual TimeSpan ToTime { get; set; }
}

And then NHibernate does have a special type to handle this trick:

Map(c => c.FromTime)
   .Type<NHibernate.Type.TimeAsTimeSpanType>();
...

That will allow you to work with a .NET native "time like" type -

MSDN - TimeSpan Structure

Represents a time interval.

What is the NHibernate.Type.TimeType then?

If we prefer to use DateTime, which could be used by NHibernate to express time, we have to do it like this:

public class TimeSlot : EntityBase
{
    public virtual DateTime FromTime { get; set; }
    public virtual DateTime ToTime { get; set; }
}

And now we can use the type from the question - NHibernate.Type.TimeType

Map(c => c.FromTime)
   .Type<NHibernate.Type.TimeType>();
...

Which description is:

/// <summary>
/// Maps a <see cref="System.DateTime" /> Property to an DateTime column that only stores the 
/// Hours, Minutes, and Seconds of the DateTime as significant.
/// Also you have for <see cref="DbType.Time"/> handling, the NHibernate Type <see cref="TimeAsTimeSpanType"/>,
/// the which maps to a <see cref="TimeSpan"/>.
/// </summary>
/// <remarks>
/// <para>
/// This defaults the Date to "1753-01-01" - that should not matter because
/// using this Type indicates that you don't care about the Date portion of the DateTime.
/// </para>
/// <para>
/// A more appropriate choice to store the duration/time is the <see cref="TimeSpanType"/>.
/// The underlying <see cref="DbType.Time"/> tends to be handled differently by different
/// DataProviders.
/// </para>
/// </remarks>
[Serializable]
public class TimeType : PrimitiveType, IIdentifierType, ILiteralType

Also check:

Date/Time Support in NHibernate

... Time-related DbTypes stores just the time, but no date. In .NET, there is no Time class and so NHibernate uses a DateTime with the date component set to 1753-01-01, the minimum value for a SQL datetime or a System.TimeSpan – depending on the DbType that we choose...

like image 135
Radim Köhler Avatar answered Mar 20 '23 20:03

Radim Köhler