Search code examples
fluent-nhibernate

Using discriminator with Fluent NHibernate


I'm trying to create a discriminator column. This column would hold one of the many statuses available. Like my code will show, each status has a name as well as a background color. Each status shares the same base class.

Here is my code:

public class Item
{
    public virtual int Id { get; set; }
    public virtual Status ItemStatus { get; set; }
}

public abstract class Status
{
    private readonly int _id;
    public static readonly Status Foo = new FooStatus(1);
    public static readonly Status Bar = new BarStatus(2);

    public Status()
    {

    }

    protected Status(int id)
    {
        _id = id;
    }

    public virtual int Id { get { return _id; } }
    public abstract string Name { get; }
    public abstract string BackgroundColor { get; }
}

public class FooStatus : Status
{
    public FooStatus()
    {

    }

    public FooStatus(int id)
        : base(id)
    {

    }

    public override string Name
    {
        get { return "Foo Status"; }
    }

    public override string BackgroundColor
    {
        get { return "White"; }
    }
}

public class BarStatus : Status
{
    public BarStatus()
    {

    }

    public BarStatus(int id)
        : base(id)
    {

    }

    public override string Name
    {
        get { return "Bar Status"; }
    }

    public override string BackgroundColor
    {
        get { return "Black"; }
    }
}

And here is my mapping:

public class ItemMap : ClassMap<Item>
{
    public ItemMap()
    {
        Id(x => x.Id).GeneratedBy.Identity();

        DiscriminateSubClassesOnColumn<int>("ItemStatus", 0).AlwaysSelectWithValue();
    }
}

Essentially, what I'd like is that if I set ItemStatus to Status.Foo then the ItemStatus column would have a value of 1. What I have now doesn't throw any exceptions, but it always inserts ItemStatus as 0.

This is the inserting code I'm using:

using (var session = sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
    var item = new Item
    {
        ItemStatus = Status.Foo
    };
    session.Save(item);
    transaction.Commit();

    var firstItem = session.Get<Item>(1);
    Console.WriteLine(firstItem.ItemStatus.Name);
}

Where can I read up on this topic using FNH?

Before anyone suggests be to check on Google I did search several things but nowhere can I find a full example.


Solution

  • Your SubclassMap would look something like this:

    public class FooStatusMap : SubclassMap<FooStatus>
    {
        public FooStatusMap()
        {
            DiscriminatorValue(1);
        }
    }
    

    This is called "table-per-class-hierarchy," and you're right it doesn't look like there are many resources on it out there.

    I believe if you don't call DiscriminatorValue in a SubclassMap, NHibernate attempts to discriminate by looking at the name of the subclass being mapped and seeing if it matches up with the value in the discriminator column.