Using discriminator with Fluent NHibernate

て烟熏妆下的殇ゞ 提交于 2019-12-07 07:10:11

问题


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.


回答1:


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.




回答2:


I wouldnt write submaps for all the subclasses you can just do this instead

public class FooMap: ClassMap<T>
{
//other mapping
DiscriminateSubClassesOnColumn("DiscriminatorColumn")
.SubClass<Foo1>(m => { })
.SubClass<Foo2>(m => { })
.SubClass<Foo3>(m => { });
}

Hope that helps




回答3:


If you're open to the Discriminator column having the class names of the derived classes, you can implement this via automapping.

In your session factory:

private static ISessionFactory CreateSessionFactory()
{
    var cfg = new MyMappingConfiguration();
    return Fluently.Configure()
    .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("MyConnectionKey")).FormatSql().ShowSql()
            )
    .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Status>(cfg)
    .IncludeBase<Status>()
    .Conventions.Add<PrimaryKeyConvention>()))
    .BuildSessionFactory();
}

Then add the MyMappingConfiguration override:

public class MappingConfiguration : DefaultAutomappingConfiguration
{
    public override bool IsId(Member member)
    {
        return member.Name == member.DeclaringType.Name + "Id";
    }

    public override bool IsDiscriminated(Type type)
    {
        return true;
    }
}

Hope that h



来源:https://stackoverflow.com/questions/6887168/using-discriminator-with-fluent-nhibernate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!