0

I've tried searching for information on this all over the place, but no one seems to quite cover this issue. I've reduced it to the following example.

This is my database :

create table ThingTypes
(
    Id int,
    Name varchar(50) not null

    constraint PK_ThingTypes primary key (Id)
)
go

insert into ThingTypes(Id, Name) Values(1, 'ThingTypeOne')
insert into ThingTypes(Id, Name) Values(2, 'ThingTypeTwo')

create table Things
(
    Id int identity,
    Name varchar(50) not null,
    ThingTypeId int not null

    constraint PK_Things primary key (Id),
    constraint FK_Things_ThingTypes foreign key (ThingTypeId) references ThingTypes(Id)
)
go

This is my model :

public abstract class Thing
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}
public class ThingTypeOne : Thing { }
public class ThingTypeTwo : Thing { }

These are my mappings :

public class ThingOverride : IAutoMappingOverride<Thing>
{
    public void Override(AutoMapping<Thing> mapping)
    {
        mapping.DiscriminateSubClassesOnColumn("ThingTypeId", 0);
    }
}

public class ThingTypeOneMap : SubclassMap<ThingTypeOne>
{
    public ThingTypeOneMap()
    {
        DiscriminatorValue(1);
    }
}

public class ThingTypeTwoMap : SubclassMap<ThingTypeTwo>
{
    public ThingTypeTwoMap()
    {
        DiscriminatorValue(2);
    }
}

This is my ISessionFactory builder :

public static ISessionFactory GetFactory(string connectionString)
{
    var configuration = new Configuration().AddProperties(new Dictionary<string, string>
        {
            {Environment.ConnectionDriver, typeof (SqlClientDriver).FullName},
            {Environment.Dialect, typeof (MsSql2008Dialect).FullName},
            {Environment.ConnectionProvider, typeof (DriverConnectionProvider).FullName},
            {Environment.ConnectionString, connectionString},
            {Environment.ShowSql, "true"},
            {Environment.BatchSize, "100"},
            {Environment.Isolation, "ReadCommitted"}
        });

    return Fluently.Configure(configuration)
                    .Mappings(m =>
                        {
                            m.FluentMappings.AddFromAssemblyOf<ThingTypeOneMap>();
                            m.AutoMappings.Add(AutoMap.AssemblyOf<Thing>(new DefaultAutomappingConfiguration())
                                                        .UseOverridesFromAssemblyOf<ThingOverride>()
                                );
                        })
                    .BuildSessionFactory();
}

And this is my failing test :

var sessionFactory = SessionFactoryBuilder.GetFactory(@"Data Source=localhost;Initial Catalog=ThingDatabase;Trusted_Connection=True;");
using (var session = sessionFactory.OpenSession())
{
    session.BeginTransaction();
    session.SaveOrUpdate(new ThingTypeOne
        {
            Name = "New Thing Type One"
        });
    session.Transaction.Commit();
}

It fails because it tries to insert into table "ThingTypeOne", which obviously doesn't exist. What do I need to do to get Fluent NHibernate to actually pay attention to the DiscriminateSubClassesOnColumn property that I've set?

adhocgeek
  • 1,437
  • 1
  • 16
  • 30
  • I can get this working if I don't use AutoMapping, i.e. exclude all the table-per-inheritance-hierarchy classes from the auto mapping (adding && !typeof(Thing).IsAssignableFrom(type) to the ShouldMap method of my DefaultAutomappingConfiguration extension) but my base class has a lot of properties and I *really* want to use AutoMapping... – adhocgeek Nov 01 '13 at 17:05
  • specify `AutoMap.AssemblyOf().IncludeBase()` – Firo Nov 02 '13 at 08:43
  • That doesn't work because then you end up with the exception "Duplicate class/entity mapping ThingTypeOne". – adhocgeek Nov 04 '13 at 09:05

1 Answers1

2

instead of subclassmaps for each subclass add a convention

class DiscriminatorValueConvention : ISubclassConvention
{
    public void Apply(ISubclassInstance instance)
    {
        if (instance.Type == typeof(ThingTypeOne))
        {
            instance.DiscriminatorValue(1);
        }
        else if (instance.Type == typeof(ThingTypeTwo))
        {
            instance.DiscriminatorValue(2);
        }
    }
}
Firo
  • 30,626
  • 4
  • 55
  • 94