Search code examples
c#nhibernatefluent-nhibernate

NHibernate: Stateful and Stateless sessions need different mappings


I'm using Fluent NHibernate to read and write files. At the moment, I have a parent-child relationship, with the mappings defined by

public class ParentMappings: ClassMap<Parent>
{
    public ParentMappings()
    {
        Table("Parent");
        Id(x => x.Id).Column("Parent_Id");
        ...

        HasMany(x => x.Children)
            .Not.KeyNullable()
            .Not.Inverse()
            .KeyColumn("Parent_Id")
            .Cascade.All();

        ...
    }
}

and

public class ChildMappings : ClassMap<Child>
{
    public ChildMappings()
    {
        Table("Child");
        Id(x => x.Id).Column("Child_Id");

        Map(x => x.ParentId).Column("Parent_Id");
        ...
    }
}

Here is the problem. I want to be able to write to the parent/child table with a stateless session, to preserve speed, but also to read from the table with a stateful session, so that the Children collection gets loaded correctly. However, it seems that the two approaches are incompatible. The call to HasMany() breaks the statless write; removing it breaks the stateful read.

In a wider context, there may also be instances where I'll want to write to the database using a stateful session. But in that case the inclusion of the Map(x => x.ParentId).Column("Parent_Id") statement breaks the stateful write.

It looks as though I'll need to use different mappings for stateful and stateless sessions. However, I'm new to NHibernate, and I can't see an obvious way to do that at this stage. Can anyone suggest a way to do this, or an equivalent workaround?


Solution

  • you have mapped the backreference to parent in the child but it should be a reference not the id alone. Change it to

    // in childmap
    Reference(x => x.Parent).Column("Parent_Id");
    

    and then you can set inverse to enhance performance

    // in parentmap
    HasMany(x => x.Children)
            .Not.KeyNullable()
            .Inverse()
            .KeyColumn("Parent_Id")
            .Cascade.All();
    

    then the HasMany and the Map(x => x.ParentId) do not collide anymore in stateful session