1

I'm using Fluent-NHibernate and attempting to persist an object hierarchy using the table per subclass method:

public class AbstractProduct
{
    public int ProductId { get; set; }
    public string Name { get; set; }
}

public class SingleProduct : AbstractProduct
{
    public int SingleProductId { get; set; }
    public string SomeField { get; set; }
}

when saving an object

        var singleProduct = new SingleProduct();
        session.SaveOrUpdate(singleProduct);

I get this error:

NHibernate.Exceptions.GenericADOException: could not insert: [FluentNHibernateSubClassTest.SingleProduct#3][SQL: INSERT INTO SingleProductData (Field1, AbstractProduct_id) VALUES (?, ?)] ---> System.Data.SqlClient.SqlException: Invalid column name 'AbstractProduct_id'.

despite having the following overrides:

public class AbstractProductOverrides : IAutoMappingOverride<AbstractProduct>
{
    public void Override(AutoMapping<AbstractProduct> mapping)
    {
        mapping.Id(x => x.ProductId).Column("ProductId");
        //this mapping provided to illustrate the overrides are picked up
        mapping.Table("ProductsData");
        mapping.JoinedSubClass<SingleProduct>("ProductId");//ignored??
    }
}

public class SingleProductOverrides : IAutoMappingOverride<SingleProduct>
{
    public void Override(AutoMapping<SingleProduct> mapping)
    {
        mapping.Id(x => x.SingleProductId);
        mapping.Table("SingleProductData");
        mapping.Map(x => x.SomeField).Column("Field1");
    }
}

It doesn't appear to matter what column name I supply to JoinedSubClass it ignores it and uses AbstractProduct_id instead.

How can I tell nhibernate the key column is ProductId and not AbstractProduct_id?

I have a test project demonstrating the issue available here (you need to create the db)

UPDATE I've got around this by providing the following convention:

public class JoinedSubclassConvention : IJoinedSubclassConvention
{
    public void Apply(IJoinedSubclassInstance instance)
    {
        if (instance.EntityType == typeof(SingleProduct))
            instance.Key.Column(("ProductId"));
    }
}

which works but feels like its the wrong way or a hack.

wal
  • 17,409
  • 8
  • 74
  • 109

1 Answers1

2

mapping.Id in SingleProductOverrides is flawed. Subclasses don't have their own id, they inherit the Id from their base classes. Even mapping.JoinedSubClass<SingleProduct>("ProductId"); is redundant (probably ignored) if SingleProduct is automapped as well (it is as seen from the Override for it). JoinedSubclassConvention is the right way to do this.

Firo
  • 30,626
  • 4
  • 55
  • 94
  • do you have any reference for this (for further reading) please?. Why is it that in `AbstractProduct` the column override is respected but not in the sub-classes?, Please explain the situation where `JoinedSubclass("keyColumn") is used – wal Jan 26 '12 at 14:17
  • JoinedSubclass("keyColumn") is used when you excluded the subclass from automapping. – Firo Jan 26 '12 at 15:54
  • Thanks (again). Could I point you in the direction of http://stackoverflow.com/questions/9108388/mapping-nhibernate-parent-child-relationship-the-other-way-round ? :) – wal Feb 02 '12 at 13:47