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

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

Related

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: ignore interfaces/abstract classes during BuildSchema or UpdateSchema

Edit
I've got an interface that I'd like to base some classes on. When I go to BuildSchema (or UpdateSchema), Nhibernate creates a table for the interface. I thought I found a work-around as follows:
The Interface and Classes:
public interface ILevel
{
int Id { get; set; }
string Name { get; set; }
}
public abstract class Level : ILevel
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
public class LevelOne : Level { }
public class LevelTwo : Level { }
The Mappings:
public class LevelMap : ClassMap<ILevel>
{
public LevelMap()
{
Id(x => x.Id);
Map(x => x.Name);
}
}
public class LevelOneMap : SubclassMap<LevelOne>
{
}
public class LevelTwoMap : SubclassMap<LevelTwo>
{
}
This doesn't work (I did another UpdateSchema and the pesky ILevel table appeared).
Is there a configuration I'm unaware of to ignore interfaces/abstract classes altogether?
For seperate tables LevelOne and LevelTwo, that both have the properties of Level/ILevel, use a generic mapping for Level:
public abstract class LevelMap<T> : ClassMap<T>
where T : Level // ILevel should work, too
{
protected LevelMap()
{
Id(x => x.Id);
Map(x => x.Name);
}
}
public class LevelOneMap : LevelMap<LevelOne>
{
}
public class LevelTwoMap : LevelMap<LevelTwo>
{
}
You provide two separate class mappings without telling Fluent the real class hierarchy.

Why doesn't this class hierarchy fluent mapping work?

What's wrong with my mapping shown below? Is this a problem with GeneratedBy.Foreign()? How should I use it cause my PK in UserTable(UID) is also the FK which refers to PersonTable PK(PID). I get the Duplicate class/entity mapping consoleMappingTest.SystemUser error. what do you suggest(be sure to look at database structure- no way to change it). thanks.
Inheritance structure:
public class Person
{
public virtual int ID { get; set; }
}
public class User:Person
{
public override int ID
{
get
{
return base.ID;
}
set
{
base.ID = value;
}
}
public virtual string Name { get; set; }
public virtual int Salary { get; set; }
}
public class SystemUser:User
{
public virtual int Password { get; set; }
}
Database structure:
for saving some info about person(some fields not shown here):
PersonTable(PID)
for saving User and all it's subclasses like system user:
UserTable(UID,Name,Salary,Type)
and here is my mapping:
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Table("PersonTable");
Id(x => x.ID, "PID").GeneratedBy.Assigned();//or HiLo-not important
}
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
Table("UserTable");
DiscriminateSubClassesOnColumn("Type").Default("U");
Id(x => x.ID, "UID").GeneratedBy.Foreign("Person");//how should use this?
Map(x => x.Salary);
Join("PTable", j =>
{
j.KeyColumn("UID");
j.Map(x => x.Name);
});
}
}
public class SystemUserMap : SubclassMap<SystemUser>
{
public SystemUserMap()
{
DiscriminatorValue("SU");
Map(x => x.Password);
}
}
Foreign("") is meant to point to a Reference (Property with another mapped entity) from which the Id should be retrieved. You don't have a Reference to class Person named Person so you can't use it like this.
you already asked the same question with an answer. I know i didn't do it right first shot but would be nice if you told me what doesnt work with the latest edit or you dont like the solution befor asking the same question again

How to do inheritance in fluent NH without discriminator type column

I have 2 classes:
public class MyBaseClass
{
public virtual int Id { get; set; }
public virtual string BaseProperty { get; set; }
}
public class MyClass : MyBaseClass
{
public virtual string ChildProperty { get; set; }
}
I want to map each of them to its own table (fluent NH). How to do it with no discriminator type column added to [MyBaseClass] table? So I expect [MyBaseClass] table consists of BaseProperty and Id columns only, MyClass consists of Id, BaseProperty and ChildProperty columns.
Thanks
You can try to put IgnoreBase to on MyBaseClass. It will say for FNH to map those classes independently
I've just found this (http://wiki.fluentnhibernate.org/Fluent_mapping#Components):
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Child : Parent
{
public string AnotherProperty { get; set; }
}
If you wanted to map this as a
table-per-subclass, you'd do it like
this:
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Id(x => x.Id);
Map(x => x.Name);
}
}
public class ChildMap : SubclassMap<Child>
{
public ChildMap()
{
Map(x => x.AnotherProperty);
}
}
So looks like this approach does not require any Db changes like adding special fields to my tables. The only problem is I do not know how to do the same in AutoMapping with Override statements. We do mapping this way:
public class AutoMappingConfiguration : DefaultAutomappingConfiguration
{
public override bool IsDiscriminated(Type type)
{
return true;
}
public override bool ShouldMap(Type type)
{
return type.In(typeof(MyBaseClass),typeof(MyClass),...)
}
...
}
FluentNHibernate.Automapping.AutoPersistenceModel Instance =
AutoMap.AssemblyOf<MyBaseClass>(new AutoMappingConfiguration())
.Override<MyBaseClass>(m =>
{
...
}
}
So I'm not sure how to apply SubClass instruction in my case. Any advise?
Thanks.

Fluent NHibernate - How to use an enumerator to identify subclass?

Im trying to map the following classes:
public abstract class ScheduleType
{
public virtual int Id { get; set; }
public virtual TypeDiscriminatorEnum Discriminator { get; set; }
}
public class DerivedScheduleType : ScehduleType
{
public virtual bool MyProperty { get; set; }
}
public class ScheduleTypeMap : ClassMap<ScheduleType>
{
public ScheduleTypeMap()
{
Id(p => p.Id);
Map(p => p.Discriminator).CustomType<TypeDiscriminatorEnum>().Not.Nullable();
}
}
public class DerivedScheduleTypeMap : SubclassMap<DerivedScheduleType>
{
public DerivedScheduleTypeMap()
{
//DiscriminatorValue(TypeDiscriminatorEnum.DerivedSchedule);
Map(p => p.MyProperty);
}
}
The problem is that queries on ScheduleType joins with all derived tables to find the right one.
I need something that says to NHibernate to join only with the table that represents the right subclass.
Any sugestions?
Thanks in advance!
Use DiscriminateSubClassesOnColumn<TypeDiscriminatorEnum>("discriminator") instead of Map(p => p.Discriminator).
I'm not quite sure what you're trying to achieve though, because you're talking about joining other tables; discriminators aren't used with table-per-subclass, only in table-per-class-hierarchy.