Search code examples
c#nhibernatefluent-nhibernate

Fluent NHibernate Mapping a join table without a primary key


I have an existing database that has three tables, two entity tables and a link table. Each of the two entity tables have a primary key, id. One uses an int and one uses a guid. The join table contains two columns, the primary key of each table. So, roughly it looks like this:

Table 1: Question Id - primary key, int

...

Table 2: Asset Id - primary key, guid

...

Table 3: QuestionAsset

Asset - (PK, FK guid)

Question - (PK, FK, int)

I have my classes setup as follows:

public class NQuestion
{
    public virtual int Id { get; set; }
    ...
    public virtual IList<NQuestionAsset> Assets { get; set; }
}

public class NQuestionAsset
{
    public virtual NAsset Asset { get; set; }
    public virtual NQuestion Question { get; set; }
}

public class NAsset
{
    public virtual Guid Id { get; set; }
    ...
}

public class QuestionMap : ClassMap<NQuestion>
{
    public QuestionMap()
    {
        Table("Question");
        LazyLoad();

        Id(q => q.Id).GeneratedBy.Identity().Column("Id");
        ...
        HasManyToMany(x => x.Assets).Table("QuestionAsset")
            .ParentKeyColumns.Add("Asset", "Question")
            .Not.LazyLoad();
     }
 }

 public class QuestionAssetMap : ClassMap<NQuestionAsset>
    {
    public QuestionAssetMap()
    {
        Table("QuestionAsset");
        LazyLoad();

        CompositeId().KeyProperty(a => a.Asset, "Id").KeyProperty(a => a.Question, "QuestionId");

        References(a => a.Asset.Id).Column("Asset");
        References(a => a.Question.QuestionId).Column("Question");
    }
}

public class AssetMap : ClassMap<NAsset>
{
    public AssetMap()
    {
        Table("Asset");
        LazyLoad();

        Id(q => q.Id).GeneratedBy.GuidComb().Column("Id");
        ...
    }
}

I have tried more iterations of relationships than I care to admit to get the link table to populate. How do I define this relationship? I can't change the database.

Right now, with the code above I am getting the following exception:

Could not determine type for: Question.Model.NHibernate.NAsset, Question, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null, for columns: NHibernate.Mapping.Column(Id)


Solution

  • In case,

    • the pairing table does not have its own ID column
    • has only two columns, foreign keys

    We should not introduce the pairing object, and just map both ends directly

    public class NQuestion
    {
        public virtual int Id { get; set; }
        ...
        //public virtual IList<NQuestionAsset> Assets { get; set; }
        public virtual IList<Asset> Assets { get; set; }
    

    and the HasManyToMany will work

    public QuestionMap()
    {
        ...
        HasManyToMany(x => x.Assets)
             .Table("QuestionAsset")
             .ParentKeyColumn("Asset")
             .ChildKeyColumn("Question")
             ...;
    

    See more here