views:

340

answers:

2

Hi guys,

I'm quite new to the whole concept of ORM, NHibernate and FluentNH, and i'm trying to accomplish something that seems so simple...

I'm trying to retrieve an object that has a field defined as Int64 in it's class. This field would be the ID, as defined in the Map file.

When trying to retrieve a record from the DB, NHibernate returns the following error message : "Provided id of the wrong type. Expected: System.Int32, got System.Int64"

I have a very simple object :

public class Holiday
{
    public virtual Int64 HolidayID { get; set; }
    public virtual string Name { get; set; }
    public virtual int Day { get; set; }
    public virtual int Month { get; set; }
    public virtual bool IsActive { get; set; }
    public virtual HolidayGroup Group { get; set; }

    public Holiday() { }

}

the Mapping file (for FluentNH) is the following :

public class HolidayMap : ClassMap<Holiday>
{
    public HolidayMap()
    {

        Id(x => x.HolidayID);
        Map(x => x.Name);
        Map(x => x.Day);
        Map(x => x.Month);
        Map(x => x.IsActive);
        HasOne(x => x.Group);
    }
}

the table structure (generated by NH) is the following:

CREATE TABLE [dbo].[Holiday](
 [HolidayID] [bigint] IDENTITY(1,1) NOT NULL,
 [Name] [nvarchar](255) NULL,
 [Day] [int] NULL,
 [Month] [int] NULL,
 [IsActive] [bit] NULL,
 [HolidayGroup_id] [int] NULL,
PRIMARY KEY CLUSTERED 
(
 [HolidayID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

and finally, i am trying to retrieve the Holiday instance using this:

    public static Holiday Get(Int64 _holidayID)
    {
        Holiday _holiday = new Holiday();

        try
        {
            using (var session = Global.NHibernate_SessionFactory.OpenSession())
            {
                _holiday = session.Get<Holiday>(_holidayID); // EXCEPTION OCCURS HERE
            }
        }
        catch (Exception _ex)
        {
            // TODO : Implement proper logging
        }

        return _holiday;
    }

What am i doing wrong?? What's missing? When deleting the table and redefining my object using an Int32 for the ID, everything works! I need use a bigger type!

Many thanks!

EDIT 1 : As Aaronaught mentions, i agree, my need for an Int64 is a bit of overhead for storing holidays... But for a second, let's forget the "Holidays" concept. What am i going to do with my logging table (5 to 10 events (rows) per seconds!). Thanks!

EDIT 2 : @Paco : I'm using NHibernate 2.1.2.4000 and FluentNH 1.0.0.614

EDIT 3 : After rerading Daniel Schilling's solution, rebuilt a (brand new) simple Holiday object that used an Int64 as an ID. I was able to retrieve a record from the DB successfully. As soon as i added a relationship to a Group object, when instanciating a Holiday object i received the same error message as earlier... Here is the HolidayGroup class and mapping, in case you can tell me what i did wrong...

public class HolidayGroup
{
    public virtual int HolidayGroupID { get; set;}
    public virtual string Name { get; set; }
    public virtual string Notes { get; set; }
    public virtual bool IsActive { get; set; }
    public virtual IList<Holiday> Holidays { get; set; }

    public HolidayGroup()
    {
        Holidays = new List<Holiday>();
    }
}

public HolidayGroupMap() { Id(x => x.HolidayGroupID); Map(x => x.Name); Map(x => x.Notes); Map(x => x.IsActive); HasMany(x => x.Holidays) .Cascade.All() }

A: 

Have you tried this?

public class HolidayMap : ClassMap<Holiday>
{
    public HolidayMap()
    {

        Id(x => x.HolidayID).SetAttribute("type", "Int64");
        Map(x => x.Name);
        Map(x => x.Day);
        Map(x => x.Month);
        Map(x => x.IsActive);
        HasOne(x => x.Group);
    }
}
Chris Conway
Apparently the "SetAttribute" was removed from FluentNH in version 1.0 (http://wiki.fluentnhibernate.org/Release_notes_1.0)
EtienneStG
Tried the following with no luck : Id(x => x.HolidayID) .CustomType(typeof(Int64));(Same result => "Provided id of the wrong type. Expected: System.Int32, got System.Int64")
EtienneStG
+2  A: 

I know it's not really helpful to just say that it works for me, but ... it works for me. I use long for my id's all the time with Fluent NHibernate. My versions:

  • NHibernate 2.1.0.4000
  • Fluent NHibernate 1.0.0.598

As others have commented, it's possible that this could be a problem with NHibernate or Fluent NHibernate. To figure out where the problem is, use the ExportTo method to find out what *.hbm.xml Fluent NHibernate is generating. See the "Exporting mappings" section on http://wiki.fluentnhibernate.org/Fluent_configuration.

If FluentNHibernate is working correctly, you should see something like ...

<id name="HolidayID" type="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="HolidayID" />
  <generator class="identity" />
</id>

... in the *.Holiday.hbm.xml file. If you see that System.Int64, then the issue must be in NHibernate or in your code. If the problem is with NHibernate - it must be a problem introduced since 2.1.0 (since it works for me). Try using the same version I'm using. If the problem goes away, then it was the new version of NHibernate's fault.

If that doesn't fix the problem, then (unfortunately) the problem most likely lies in your own code. How is Global.NHibernate_SessionFactory instantiated? Is it possible that one Configuration object is being used to export the schema and another instance is creating the SessionFactory?

Those are all the ideas I have. Good luck.

EDIT 1: Regarding the relationship to HolidayGroup (sorry - didn't notice that before): I think you mean References instead of HasOne - see question 1622007. Also, you need to mark one side of the relationship Inverse() - typically you would put that on the HasMany side.

EDIT 2: The incorrectly applied HasOne is surely the source of this error. One-to-one relationships are mapped by default with two tables that share primary keys in common. The child's primary key column would typically have a foreign key relationship to the parent's primary key. By saying "Holiday has-one HolidayGroup", you set Holiday up as the parent and HolidayGroup as the child (which is the reverse of what you wanted).

When NHibernate tries to load the Holiday that is associated with the HolidayGroup, it will take HolidayGroup's Int32 ID and try to retrieve a Holiday that has the same ID. However, Holiday has a Int64 ID, hence the error.

Make the changes under "EDIT 1", and this problem should go away.

  1. Change the HasOne to References.
  2. Add Inverse() to HolidayGroup's HasMany.
Daniel Schilling
Thanks Daniel! It worked! Thanks for the explanation!
EtienneStG