使用Fluent NHibernate的鉴别器

时间:2011-07-31 02:27:00

标签: fluent-nhibernate

我正在尝试创建一个鉴别器列。此列将包含许多可用状态之一。就像我的代码一样,每个状态都会显示一个名称和一个背景颜色。每个状态共享相同的基类。

这是我的代码:

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"; }
    }
}

这是我的映射:

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

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

基本上,我想要的是,如果我将ItemStatus设置为Status.Foo,那么ItemStatus列的值为1.我现在所拥有的不会抛出任何内容异常,但始终将ItemStatus作为0插入。

这是我正在使用的插入代码:

        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);
        }

我在哪里可以使用FNH阅读此主题?

在有人建议检查Google之前,我确实搜索了几件事,但没有找到完整的例子。

3 个答案:

答案 0 :(得分:3)

您的SubclassMap看起来像这样:

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

这称为“每个类的表层次结构”,你说它是正确的,看起来它上面有很多资源。

相信如果你没有在DiscriminatorValue中调用SubclassMap,NHibernate会通过查看被映射的子类的名称并查看它是否匹配来尝试区分使用鉴别器列中的值。

答案 1 :(得分:0)

我不会为所有子类编写子图,而是可以这样做

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

希望有所帮助

答案 2 :(得分:0)

如果你对具有派生类的类名的Discriminator列开放,你可以通过自动化来实现它。

在你的会话工厂中:

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();
}

然后添加MyMappingConfiguration覆盖:

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;
    }
}

希望h