Fluent NHibernate Polymorphic Mapping Challenges - fluent-nhibernate

I am having some problems mapping the following scenario in Fluent Nhibernate using Table Per Concrete class:
Let's say I have the following class definitions:
public class Reading { .... }
public class CarReading : Reading { .... }
public class TruckReading : Reading { .... }
public class Alert
{
....
public virtual Reading AReading { get; set; }
}
So my question is how to create the mapping class for Alert, if it has a one to one relationship with reading class (could be either truck reading or car reading) and instruct nhibernate to know which table to load the data from (TruckReading table or CarReading Table)
public class AlertMap : ClassMap<Alert>
{
....
HasOne(x => x.AReading);
}
If anyone could point me in the right direction that would be much appreciated.
Thanks.

public class AlertMap : ClassMap<Alert>
{
....
ReferenceAny(x => x.AReading)
.EntityIdentifierColumn("readingid")
.EntityTypeColumn("readingtype")
.IdentityType<int>()
.AddMetaValue<CarReading>("car")
.AddMetaValue<TruckReading>("truck");
}

Related

nhibernate join table value function

I'm discovering nhibernate right now. Thus my question is maybe very stupid :)
What I'm trying to do (I'm working with a legacy database) is to get an entity which some of its data are coming from a table value function.
My entity is the following
public class Entity
{
public virtual int Id { get; protected set; }
....
public virtual int AccessRightId { get; set; }
}
where AccessRightId comes from the table value function (fp_AccessRight('userId'))
I have the following mapping
public class EntityMap : ClassMap<Entity>
{
public EntityMap ()
{
this.Id(entity => entity .Id);
this.Join(
"fp_AccessRight('userId')",
join =>
{
join.Fetch.Join();
join.KeyColumn("EntityId");
join.Map(t => t.AccessRightId, "AccessRightType");
join.Table();
});
}
}
Unfortunately, I'm not able to substitute 'userId' by any value.
Thanks.
Is there a way to do it?
I finally solved it.
The trick was to make the join like this :
this.Join("fp_ACCOUNT_ACL(:AclFilter.userId)"
and then simpley to enable the filter
this.session.EnableFilter("AclFilter").SetParameter("userId", "bdd#5");
I found an example here.

Loading a base class through nhibernate incorrectly uses mappings from derived classes

I have a scenario where I have a base class as one entity, then another entity that derives from the other base class. Both have meaning in my domain and can be used separately.
public class MyBaseClass
{
int ID { get; set; }
string Name { get; set; }
}
public class MyChildClass
{
string AdditionalField { get; set; }
}
I have both mapped using Fluent nHibernate using ClassMap like this:
public class MyBaseClassMap : ClassMap<MyBaseClass>
{
Id("MyBaseClassID");
Map(x => x.Name);
}
public class MyChildClassMap : SubclassMap<MyChildClass>
{
Map(x => x.AdditionalField);
}
What is happening is when I try to fetch a copy of the base class, its using the mapping for the child class. Its as if it doesn't know the the difference between the base and child class, or its choosing the wrong mapping for it. I confirmed this by watching the SQL statement and its joining to the child table and fetching the additional column. Any way to get it to use the right map?
That's the 'nature' of NHibernate.
The behaviour you're describing, is called 'polymorphic queries'.
Since MyChildClass is a MyBaseClass, the MyChildClass instances are retrieved as well.
If you want to avoid this behaviour, you can maybe have a look at the answers in this topic. (I've never 'disabled' the polymorphic query ability).

FluentNHibernate override generic class

How to override the mapping of generic class?
I have this class:
public abstract class TranslatableEntity<TTranslation, TEntity> : Entity
{
public virtual String Name { get;set; }
// ...
}
And I whant to do this:
public class TranslatableEntityMap<T> : IAutoMappingOverride<TranslatableEntity<T>>
{
public void Override(AutoMapping<TranslatableEntityMap<T>> mapping)
{
mapping.IgnoreProperty(x => x.Name);
}
}
How can I do this?
Thank you!
AFAIK It is not possible. More over it has no sense to map generic class sice mapping requires the real class with implementation.
I don't think it is possible to map generic classes with NHibernate.

Optional SubclassMap (left join) with NHibernate 3.0 GA & FNH

Disclaimer: I'm fairly new to NH & ORM in general.
Disclaimer: I'm working with a build of FNH from here in order to use with NH3.0GA.
The problem in a nutshell is that I would like to use FNH's SubclassMap as a way to map a LEFT JOIN, table-per-subclass scenario to my object hierarchy which is defined as:
public class MyBaseClass {
public virtual int Id { get; set; }
}
public class MySubClass : MyBaseClass {
public virtual string SubClassVal { get; set; }
}
This is mapped via FNH as:
public class MyBaseClassMap : ClassMap<MyBaseClass> {
public MyBaseClassMap() {
Table("BaseClass");
Id(x => x.Id, "Id").GeneratedBy.Assigned();
}
}
public class MySubClassMap : SubclassMap<MySubClass> {
public MySubClassMap() {
Table("SubClass");
KeyColumn("Id");
Map(x => x.SubClassVal);
}
}
And I retrieve via:
public class Repository {
ISession session; //assume properly initialized ISession
public IList<T> GetAll<T>() where T: class {
return session.CreateCriteria<T>().List<T>();
}
}
And in my database, I've got 1 record in my BaseClass table, 0 records in SubClass.
Now, what I would like to do is pull the entity out as a MySubClass instance by doing something like this:
var rep = new Repository();
var subclasses = rep.GetAll<MySubClass>();
And of course, there are no instances in the returned collection as this is presumably performing an INNER JOIN underneath it all. This is where I'm stuck. I've managed to discover that specifying an 'optional' join is what I'm supposed to do. I've attempted to modify MySubClassMap to:
public class MySubClassMap : SubclassMap<MySubClass> {
public MySubClassMap() {
Join("SubClass", j => {
j.KeyColumn("Id");
j.Optional();
j.Map(x => x.SubClassVal); // note that I've tried the map outside the Join() below, to no avail
});
//Map(x => x.SubClassVal);
}
}
Compiling/running this presents me with the following (innermost) exception:
The element 'joined-subclass' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'join' in namespace 'urn:nhibernate-mapping-2.2'. List of possible elements expected: 'property, many-to-one, one-to-one, component, dynamic-component, properties, any, map, set, list, bag, idbag, array, primitive-array, joined-subclass, loader, sql-insert, sql-update, sql-delete, resultset, query, sql-query' in namespace 'urn:nhibernate-mapping-2.2'.
I'll save posting the stack trace, but the jist of it is:
MyApp -->
FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory() -->
NHibernate.Cfg.FluentConfiguration.BuildConfiguration()
I think that's all the relevant info. I suspect I may be bumping into a breaking change between this very new version of NH and version of FNH that isn't so new. But, as mentioned earlier, I am a rookie, and could well be doing something stupid. If this is the case, I'd very much appreciate somebody smacking me over the head with what probably should be obvious.
Thanks in advance.
Entities have one type, which doesn't change. If you have a record in your BaseClass table only, that entity is and will always be a MyBaseClass.
If entities can change their "type", you shouldn't use inheritance but composition.

NHibernate Component inheritance

Is it possible to do inheritance with NHibernates component? A quick google returned only a hand full of appropriate results (all blogs) and all were written some time ago so was wondering if it is available yet?
if not how do you handle it instead?
It's not currently possible. If you need inheritance, you have to map an entity.
In addition to what Diego had said, there is also an option to implement custom hydration/dehydration for hierarchy using IUserType. See this article for details (its Java but the same mechanism can be used in C#).
And Hibernate feature request is here. NHibernate version is here, please vote.
Yes.
public class A { }
public class B : A { }
public sealed class C : B { }
public abstract class BaseAMap<T> : ComponentMap<T> where T : A {
public BaseAMap() {
// Map A here
}
}
public class AMap : BaseAMap<A> {
}
public class BaseBMap<T> : BaseAMap<T> where T : B {
public BaseBMap () {
// Map B (excluding A)
}
}
public class BMap : BaseBMap<B> {
}
public sealed class CMap : BaseBMap<B> {
public CMap () {
// Map C (excluding B)
}
}