Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fluent NHibernate mapping on multiple non-PK fields

I have a situation similar to that described in Fluent NHibernate Mapping not on PK Field

However, the relationship between my tables is described by multiple non-primary key columns. Imagine Chris Meek's situation but where a Person has a JobType and a Code that, together, should (sorry, it's a legacy database) uniquely describe a Person

Person
------
Id PK
JobType
Code
Name

Order
-----
Id PK
Person_JobType
Person_Code
OrderDetails

Serhat Özgel's answer describes using PropertyRef, but I can't find a way to do that individually for multiple columns. I've tried similar to

class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        HasMany(p => p.Order)
            .KeyColumns.Add("Person_JobType")
            .PropertyRef("JobType")
            .KeyColumns.Add("Person_Code")
            .PropertyRef("Code")
    }
}

But this obviously doesn't work, since KeyColumns.Add() returns another OneToManyPart so PropertyRef() isn't being run against the individual column being added. The second PropertyRef() simply overwrites the first one, and I get the following error:

NHibernate.MappingException : collection foreign key mapping
has wrong number of columns: MyApp.Person.Order type: Int32

I've looked at the various overloads of KeyColumns.Add(),

public TParent Add(string name)
public TParent Add(params string[] names)
public TParent Add(string columnName, Action<ColumnPart> customColumnMapping)
public TParent Add(ColumnMapping column)

Specifically the last two, but couldn't find any way to set PropertyRef individually level for each column :( Is there a way to do that? Am I going about this the wrong way entirely?

like image 243
mo. Avatar asked Oct 22 '22 08:10

mo.


1 Answers

using hbm.xml and FluentNHibernate it is possible with a trick

class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Map(_ => JobTypeAndCode)
            .Columns.Add("Person_JobType", "Person_Code")
            .ReadOnly()
            .LazyLoad() // optional: prevent loading the Columns twice
            .Access.None();

        HasMany(p => p.Orders)
            .KeyColumns.Add("Person_JobType", "Person_Code")
            .PropertyRef("JobTypeAndCode")
    }

    private object JobTypeAndCode { get; set; } // FakeProperty
}

Note: i never got this to work using NHibernate MappingByCode

like image 56
Firo Avatar answered Oct 24 '22 03:10

Firo