Fluent NHibernate - mapping multiple levels of inheritance with multiple discriminators - fluent-nhibernate

With the following class hierarchy - what would the DiscriminateSubClassesOnColumn("").Formula([insert custom sql here]) statements look like?
public abstract class Base
{
public virtual string FEE_IND { get; set; }
public virtual string REC_PAY { get; set; }
}
// FEE_IND == "03"
public abstract class Child : Base
{}
// FEE_IND == "03"
// REC_PAY == "P"
public class ChildChild : Child
{}
I haven't been able to find anything that I could wrap my head around.

.Formula("Concat(FEE_IND, REC_PAY)")
// Child
.DiscriminatorValue("03");
// ChildChild
.DiscriminatorValue("03P");

Related

Map two classes to the same table

There is a NODES table with dozen of 'small' columns and a LOB column in a legacy DB. A NodeEntity class is mapped to the NODES table.
For performance purposes I do not want to load LOB column every time I access the DB. I know two approaches to achieve this:
Lazy loaded properties
Separate entity class (the idea is taken from here)
Lazy loaded properties are good when you only loading data from DB. But if you have to save entities then there is a risk to lose your data if you forget to fetch lazy loaded properties beforehand.
So I chose the second approach.
I created separate small NodeEntityLite class with properties mapped to non-LOB columns of NODES table. I modified NodeEntity class so it inherits from NodeEntityLite class. I changed the mappings for my classes and used union-subclass for inheritance.
public class NodeEntityLite {
public virtual long Id { get; set; }
public virtual string Code { get; set; }
}
public class NodeEntity : NodeEntityLite {
public virtual string NOTE { get; set; } // type:clob
}
FluentNHibernate mapping for NodeEntityLite class is
public void Override(AutoMapping<NodeEntityLite> mapping) {
mapping.Table("NODES");
mapping.UseUnionSubclassForInheritanceMapping();
}
FluentNHibernate mapping for NodeEntity class is
public void Override(AutoMapping<NodeEntity> mapping) {
mapping.Table("NODES");
mapping.Map(e => e.NOTE).CustomType("StringClob").CustomSqlType("NCLOB");
}
I expected that when I execute select n from NodeEntityLite n where n.Id = :p0 HQL then NHibernate generates SQL commands without NOTE column:
select nodeentity0_.ID as id1_87_,
nodeentity0_.CODE as code2_87_
from from NODES nodeentity0_
where nodeentity0_.ID=:p0;
But NHibernate generates absolutely different SQL command (NOTE column is not skipped as I expected):
select nodeentity0_.ID as id1_87_,
nodeentity0_.CODE as code2_87_,
nodeentity0_.NOTE as note14_87_,
nodeentity0_.clazz_ as clazz_
from ( select ID, CODE, NOTE, 1 as clazz_ from NODES ) nodeentity0_
where nodeentity0_.ID=:p0;
I tried to change inheritance and to use other mappings but without success.
The question is: Can I map several classes to the same table in NHibernate to get access to different columns?
If yes, please give an example.
The solution (based on the suggestions from David Osborne and mxmissile) is not to use inheritance. I use common interface implementation instead of class inheritance. The working code is below:
public interface INodeLite {
long Id { get; set; }
string Code { get; set; }
}
public class NodeEntityLite : INodeLite {
public virtual long Id { get; set; }
public virtual string Code { get; set; }
}
public class NodeEntity : INodeLite {
public virtual long Id { get; set; }
public virtual string Code { get; set; }
public virtual string NOTE { get; set; } // type:clob
}
...
public void Override(AutoMapping<NodeEntityLite> mapping) {
mapping.Table("NODES");
}
...
public void Override(AutoMapping<NodeEntity> mapping) {
mapping.Table("NODES");
mapping.Map(e => e.NOTE).CustomType("StringClob").CustomSqlType("NCLOB");
}
Regardless of the inheritance, NH can map different types to the same table. I have done it, albeit without inheritance.
You should be able to remove this line from the NodeEntityLite override and achieve it:
mapping.UseUnionSubclassForInheritanceMapping();
If this proves unsuccessful, you might need to tune the automapping further. It's definitely possible though.

Auto mapper skip item if a child have NULL value

I have a problem in data transformation with AutoMapper that completely skip parent class after mapping to Dto when a member of parent is NULL.
Parent class:
public class Parent : BaseEntity
{
public string Something { get; set; }
public string SomthingElse { get; set; }
public Member Member { get; set; }
}
Parent Dto class:
public class ParentDto : BaseEntity
{
public string Something { get; set; }
public Member Member { get; set; }
}
Member class:
public class Member : BaseEntity
{
public string MemberName { get; set; }
public int? SomethingId { get; set; }
}
When we mapped parent class to Dto and if Member was not NULL all thing work like a charm but problem is when the Member is NULL parent model completely skipped in result. I have no exception or error, just parent class that have NULL Member was skipped in results.
Result generated by LINQ:
var results = await query
.Skip(pageNumber * pageSize)
.Take(pageSize)
.ProjectTo<ParentDto>()
.ToArrayAsync(ct);
Mapping created like this:
CreateMap<Parent, ParentDto>();
Packages version:
AutoMapper 6.1.1
Microsoft.AspNetCore 2.0.0
Microsoft.EntityFrameworkCore.InMemory 2.0.0
Did you have any idea that help me what is the problem and how can i solve it?

Fluent Nhiberante sub class same table as class

I have two classes:
class User {
public int Id { get;set; }
public string Name { get; set; }
}
class VerifiedUser : User {
public ICollection<Verified> { get; set; }
}
I would like NHibernate to treat VerifiedUser and User as the same table but keep them separate to, so.
Session.Query<User>() //would return a User
Session.Query<VerifiedUser>() //would return a VerifiedUser
Is this possible or is it unsupported?
You will need to implement the table-per-hierarchy strategy with Fluent Nhiberate in mapping classes. These are like overrides for the AutoMapping feature (if used) of FNH, otherwise mapping classes are de facto and you will be used to them.
Something like:
public class UserMappingOverride : IAutoMappingOverride<User>
{
public void Override(AutoMapping<User> mapping)
{
mapping.DiscriminateSubClassesOnColumn("IsVerified").Not.Nullable();
}
}
public class VerifiedUserClassMap : SubclassMap<VerfiedUser>
{
public VerifiedUserClassMap()
{
DiscriminatorValue("Yes");
}
}
And to answer your question, yes as far as I remember nothing to do here: Session.QueryOver<VerifiedUser>() as NHibernate will add on the where clause for the discriminator

Fluent Nhibernate map list of lists

I am writing mapping for the class with Fluent Nhibernate:
public class UniqueFeaturesSet : IEntity
{
public UniqueFeaturesSet(List<List<double>> mfcc)
{
MFCC = mfcc;
}
public virtual List<List<double>> MFCC { get; set; }
public virtual int Id { get; set; }
}
How to map List<List<double>> ?
It is not possible to map nested collections with [Fluent][N]Hibernate. The inner collection needs to be in an own class.

Fluent nHibernate and mapping IDictionary<DaysOfWeek,IDictionay<int, decimal>> how to?

I have problem with making mapping of classes with propert of type Dictionary and value in it of type Dictionary too, like this:
public class Class1
{
public virtual int Id { get; set; }
public virtual IDictionary<DayOfWeek, IDictionary<int, decimal>> Class1Dictionary { get; set; }
}
My mapping looks like this:
Id(i => i.Id);
HasMany(m => m.Class1Dictionary);
This doesn't work. The important thing I want have everything in one table not in two. WHet I had maked class from this second IDictionary I heve bigger problem. But first I can try like it is now.
It's not currently possible to use nested collections of any type in NHibernate.
Instead, you should define your property as follows:
public virtual IDictionary<DayOfWeek, Class2> Class1Dictionary { get; set; }
And add a new class:
public class Class2
{
public virtual decimal this[int key]
{
get { return Class2Dictionary[key]; }
set { Class2Dictionary[key] = value; }
}
public virtual IDictionary<int, decimal> Class2Dictionary { get; set; }
}
This way, you can map both classes and dictionaries normally, and still access your dictionary as:
class1Instance.Class1Dictionary[DayOfWeek.Sunday][1] = 9.4