3
votes

I have a Vessel object that has a one-to-many relationship with a VesselDetail object. When I add a VesselDetail object to the Vessel object and try to save the Vessel object, it seems NHibernate does not add the foreign key when inserting the VesselDetail object.

Where am I going wrong here ? I just cannot figure it out.

Error message: BDN.FindVessel.Tests.Integration.NhibernateRepositoryTests.SaveVessel_ShouldAddDetailsToDb_WhenAddedToEntity: NHibernate.Exceptions.GenericADOException : could not insert: [BDN.FindVessel.Domain.VesselDetail][SQL: INSERT INTO BoatsDetails (SaftyGear, OtherMachineryAndGear, Material, Size, Various, TranslatorId, SpeenAndConsumption, MainMachinery, Created, Class, Capasities, Culture, Interior, Electronics, DeckGear) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); select SCOPE_IDENTITY()] ----> System.Data.SqlClient.SqlException : Cannot insert the value NULL into column 'BoatId', table 'FindVesselTest.dbo.BoatsDetails'; column does not allow nulls. INSERT fails. The statement has been terminated.

public class Vessel
{
        public virtual int BoatId { get; set; }
        public virtual IList<VesselDetail> Details { get; set; }
        //...
}

public class VesselDetail
{
        public virtual int VesselDetailId { get; set; }
        //some other properties
        //..
}

public class VesselMap: ClassMap<Vessel>
{
    public VesselMap()
    {
        WithTable("Boats");

        Id(x => x.BoatId, "Id");

        //..

        HasMany(x => x.Details)
            .WithKeyColumn("BoatId") //foreign key in the BoatsDetails table
            .Cascade.All();
    }
}

public class VesselDetailMap:ClassMap<VesselDetail>
{
  public VesselDetailMap()
  {
      WithTable("BoatsDetails");

      Id(x => x.VesselDetailId, "Id");

      //...
  }
}
1

1 Answers

10
votes

It seems I was missing some fundamental NHibernate skills. Reading a little bit up on this it seems you need to let the child object be responsible for the one-to-many relation.

This fixed the problem for me:

public class VesselMap: ClassMap<Vessel>
{
    public VesselMap()
    {
        //...

        HasMany(x => x.Details)
                .Inverse()
                .WithKeyColumn("BoatId");
    }
}

public class VesselDetailMap:ClassMap<VesselDetail>
{
  public VesselDetailMap()
  {
      //..

       References(x => x.Vessel, "BoatId")
                .Cascade
                .SaveUpdate();
  }
}