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 share 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 no where can I find a full example.
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.
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
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