Is there #MappingSupperclass equivalent in NHibernate - nhibernate

I recently started the Asp Net Core project with NHibernate as an orm. I have definitely little experience with NHibernate.
I am looking for an equivalent for the #MappedSuperclass Hibernate annotation. Either I can't find a good solution or I can't use any found.
But from the beginning:
Each of my entities inherits from the base class BaseEntity, containing several technical fields / columns
public class BaseEntity
{
public virtual long id { get; set; }
public virtual DateTime inDate { get; set; }
public virtual DateTime? outDate { get; set; }
//some other properies
}
public class AnyClass : BaseEntity
{
//some AnyClass properties
}
public class AnyClassMap : ClassMapping<AnyClass>
{
public AnyClassMap()
{
Table("any_table");
//Copy/Paste to each mapping class
Id(b => b.id, x => { x.Column("id"); x.Generator(Generators.Native); x.Type(NHibernateUtil.Int64); });
Property(b => b.inDate, x => { x.Column("in_date"); });
Version(b => b.outDate, x => { x.Column("out_date"); x.Type(NHibernateUtil.DbTimestamp); });
//Some other BaseEntity properties
//some AnyClass properties
}//ctor
}
In every mapping class I repeat mappings about the properties of the base class. However, I would like to achieve something similar to:
public class BaseEntityMap : MappedSuperclassEquvalent<BaseEntity>
{
public BaseEntityMap()
{
Id(b => b.id, x => { x.Column("id"); x.Generator(Generators.Native); x.Type(NHibernateUtil.Int64); });
Property(b => b.inDate, x => { x.Column("in_date"); });
Version(b => b.outDate, x => { x.Column("out_date"); x.Type(NHibernateUtil.DbTimestamp); });
//Some other BaseEntity properties
}//ctor
}
public class AnyClassMap : ClassMapping<AnyClass>
{
public AnyClassMap()
{
Table("any_table");
//example only
IncludeMapping(BaseEntityMap.Class);
//some AnyClass properties
}//ctor
}
I know that I can use BaseEntity as ComponentMapping and then use it in the AnyClass class as property.
However, ComponentMapping does not allow id and version mapping. On the other hand, for many reasons I care about inheritance from the base entity.
Thank you in advance

Just create base mapping class based on ClassMapping with all stuff you need:
public class BaseEntityClassMapping<TBaseEntity>: ClassMapping<TBaseEntity> where TBaseEntity: BaseEntity
{
public BaseEntityClassMapping()
{
Id(b => b.id, x => { x.Column("id"); x.Generator(Generators.Native); x.Type(NHibernateUtil.Int64); });
Property(b => b.inDate, x => { x.Column("in_date"); });
Version(b => b.outDate, x => { x.Column("out_date"); x.Type(NHibernateUtil.DbTimestamp); });
//Some other BaseEntity properties
}
}
And make your mappings based on this class:
public class AnyClassMap : BaseEntityClassMapping<AnyClass>
{
public AnyClassMap()
{
Table("any_table");
//some AnyClass properties
}
}

Related

breeze deep expand with inheritance

I have some troubles with breeze and expanding deep properties. Here's the code:
public abstract class BaseEntity
{
public virtual Guid? Id { get; set; }
}
public partial class Request : BaseEntity
{
public virtual IList<ServiceBase> Services { get; set; }
public Request()
{
this.Services = new List<ServiceBase>();
}
}
public abstract class ServiceBase : BaseEntity
{
public virtual Guid? RequestId { get; set; }
public virtual Request Request { get; set; }
public virtual IList<Contact> Contacts { get; set; }
public ServiceBase()
{
Contacts = new List<Contact>();
}
}
public class ServiceTranslation : ServiceBase
{
public virtual string MyProp { get; set; }
}
public class ServiceModification : ServiceBase
{
public virtual string MyProp2 { get; set; }
}
public class BaseMapping<T> : ClassMapping<T> where T : BaseEntity
{
public BaseMapping()
{
this.Lazy(true);
//Schema("DEMO");
Id(x => x.Id, map => { map.Generator(Generators.GuidComb); });
}
}
public RequestMap()
{
this.Bag<ServiceBase>(x => x.Services, colmap =>
{
//colmap.Schema("demo");
colmap.Key(x => x.Column("RequestId"));
colmap.Inverse(false);
colmap.Cascade(Cascade.All);
}, map =>
{
map.OneToMany();
});
}
}
public ServicebaseMap()
{
this.Property(x => x.RequestId, map =>
{
map.Column("RequestId");
map.Insert(false);
map.Update(false);
map.NotNullable(true);
});
this.ManyToOne(x => x.Request, map =>
{
map.Column("RequestId");
map.NotNullable(true);
map.Cascade(Cascade.None);
});
this.Bag<Contact>(x => x.Contacts, colmap =>
{
//colmap.Schema("demo");
colmap.Table("ServiceContact");
colmap.Key(x => { x.Column("ContactId"); });
colmap.Inverse(false);
colmap.Cascade(Cascade.All);
}, map =>
{
map.ManyToMany(x => { x.Column("ServiceId"); });
});
}
public class ServicetranslationMap : JoinedSubclassMapping<ServiceTranslation>
{
public ServicetranslationMap()
{
Property(x => x.MyProp);
}
}
public class ServiceModificationMap : JoinedSubclassMapping<ServiceModification>
{
public ServiceModificationMap()
{
Property(x => x.MyProp2);
}
}
A Request contains a collection of ServiceBase(Abstract) and those ServiceBase contains contacts.
If I try to expand like this:
http://localhost:61971/breeze/EAINHibernate/Requests?$expand=Services,Services.Contacts
Contacts are never expanded. Looking through the code, I found the ExpandMap used by breeze in the InitializeWithCascade methods of NHInitializer.cs contains the type of the base class. But, when expanding, the type of the object in the collection is the concrete type, either ServiceTranslation or either ServiceModification.
What can we do in that kind of situation? Can we expect a fix?
Good catch! Yes, that's a bug and you can expect a fix.
UPDATE
Fixed now in GitHub. Fix will be included in the next release.

Different sequences for subclasses with Fluent NHibernate

I am using Fluent NHibernate and table per concrete class for inheritance mappings.
There is an abstract base class and two other subclasses.
My base class has Id column. Created tables are ok. All tables has its own Id column. But sequence is only one for these two tables.
I want to assign different sequence for every subclass.
public abstract class Base
{
public virtual int Id { get; set; }
}
public class BaseMap : ClassMap<Base>
{
public BaseMap()
{
Id(x => x.Id).GeneratedBy.Native();
}
}
public class A : Base
{
public virtual int AmountOfA { get; set; }
}
public class AMap : ClassMap<A>
{
public AMap()
{
Map(x => x.AmountOfA );
}
}
public class B : Base
{
public virtual int AmountOfB { get; set; }
}
public class BMap : ClassMap<B>
{
public BMap()
{
Map(x => x.AmountOfB );
}
}
Is this possible with Fluent NHibernate?
this is by design.
session.Get<Base>(1); would have undefined behavior because the id is not unique
consider the case when there is a reference to the base class Reference(x => x.SomeBase); with a the value 1 in the database: it would not be possible to know if A(Id: 1) or B(Id: 1) is the object referenced
if Base is only there to reuse the Id property then dont map it as own entity but create a base class
public class BaseMap<T> : ClassMap<T> where T : Base
{
public BaseMap()
{
Id(x => x.Id).GeneratedBy.Native();
}
}
public class AMap : BaseMap<A>
{
public AMap()
{
Map(x => x.AmountOfA );
}
}

Fluent NHibernate trying to map subclass of subclass using table-per-subclass

I am building an application with heavy inheritance and have a part where there exists classes, A, B and C with:
class A
class B : A
class C : B
I implemented subclass mapping as a table-per-subclass style for class B as follows:
class BMap : SubclassMap<B>
{
public BMap()
{
Extends<A>();
KeyColumn("ID");
}
}
Which works perfectly. However, when I want to implement C as follows:
class CMap : SubclassMap<C>
{
public CMap()
{
Extends<B>();
KeyColumn("ID");
}
}
It results in the error
Duplicate class/entity mapping
I browsed the Hibernate/NHibernate forum but could not find an answer to this problem.
this does work as expected with NH 3.3.1.4000
public class A
{
public virtual int Id { get; protected set; }
}
public class B : A { }
public class C : B { }
public class AMap : ClassMap<A>
{
public AMap()
{
Id(x => x.Id);
}
}
public class BMap : SubclassMap<B> { }
public class CMap : SubclassMap<C> { }
public static void Main(string[] args)
{
var config = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.InMemory().ShowSql().FormatSql())
.Mappings(m => m.FluentMappings
.Add<AMap>()
.Add<BMap>()
.Add<CMap>()
)
.BuildConfiguration();
using (var sf = config.BuildSessionFactory())
using (var session = sf.OpenSession())
{
new SchemaExport(config).Execute(true, true, false, session.Connection, null);
session.Save(new C());
session.Flush();
}
}

Fluent NHibernate: Example of a one-to-many relationship on an abstract class of a table-per-subclass implementation

I've been trying for ages to find an example (because I can't get it to work myself) of the correct mapping for a one-to-many relationship on an abstract class of a table-per-subclass implementation, in fluent nHibernate.
An example below: I'm looking to map the list of Fines on the Debt abstract base class to the Fine class.
If anyone knows of any tutorial or example they've come across before please let me know.
public abstract class Entity
{
public int Id { get; set; }
}
public abstract class Debt : Entity
{
public decimal Balance { get; set; }
public IList<Fine> Fines { get; set; }
public Debt()
{
Fines = new List<Fine>();
}
}
public class CarLoan : Debt
{
}
public class CreditCard : Debt
{
}
public class LoanApplication : Entity
{
public IList<Debt> ExistingDebts { get; set; }
public LoanApplication()
{
ExistingDebts = new List<Debt>();
}
}
public class Fine
{
public Int64 Cash { get; set; }
}
Can you tell us where exactly you're having difficulty? What have you tried?
Obviously, you'll need to declare all of your members as virtual (I assume this was an oversight in the example).
Basically, though, it would look like this:
public DebtMap : ClassMap<Debt>
{
public DebtMap()
{
Id(x => x.Id);
HasMany(x => x.Fines);
}
}
public FineMap : ClassMap<Fine>
{
public FineMap()
{
Id(x => x.Id);
// map other members
}
}
public CarLoanMap : SubclassMap<CarLoan> { }
public CreditCardMap : SubclassMap<CreditCard> { }

How to automap Table-per-class hierarchy in S#arp architecture

I am pretty new to S#harp architecture and fluent nhibernate. I was trying to build a sample solution using the template.
MappingIntegrationTest fails for me when I try to run it for the following domains
public class Component
{
public virtual string comp { get; set; }
}
public class Parent : Entity
{
public virtual string Type { get; set; }
}
public class Child1: Parent
{
public virtual Component Blah { get; set }
}
The ParentMap looks like following:
public class ParentMap : IAutoMappingOverride<Parent>
{
public void Override(AutoMapping<Parent> mapping)
{
mapping.DiscriminateSubClassesOnColumn("Type")
.SubClass<Child1>(m =>
{
m.Component(c => c.Blah, c =>
{
c.Map(x => x.comp , "comp");
}
}
}
}
The mapping integration tests fail for me
* Database was not configured through Database method.
----> NHibernate.MappingException : An association from the table Parent refers to an unmapped class: Component
Do I need to remove these classes from AutoMapper?