Search code examples
nhibernatehas-manyfluent-nhibernate-mapping

Fluent Nhibernate map a collection to a generic entity


First of all, sorry for my poor english.

I'm working on a project and i got to map some legacy tables with a new system running with Nhibernate. This system has a common table (DAT_DADO_EXTRA) to store customer provided data, using a key (ENTIDADE_RELACIONADA) to know from what table data is related and a id (ID_ENTIDADE_RELACIONADA) to know to who this is related.

I suppressed extra columns on both tables/classes to make the example short

My classes and maps are below:

public class ExtraData : Entity
{
    public ExtraData()
    {
    }

    /// <inheritdoc />
    public ExtraData(string key, IRobotRunEntry runEntry) : base(key, runEntry)
    {
    }

    public virtual string DataDescription { get; set; }
    public virtual int RelatedEntityId { get; set; }
    public virtual string RelatedEntityType { get; set; }
    public virtual string Value { get; set; }
}

and map

    public ExtractDataMap() : EntityMap<ExtraData>
    {
        Table("DAT_DADO_COMPLEMENTAR");

        Map(p => p.RelatedEntityId).Column("ID_ENTIDADE_RELACIONADA").Not.Nullable();
        Map(p => p.RelatedEntityType).Column("ENTIDADE_RELACIONADA").Not.Nullable();
        Map(p => p.DataDescription).Column("DESCRICAO").Not.Nullable();
        Map(p => p.Value).Column("VALOR").Not.Nullable();
    }

then i got a class called Document

public class Document : Entity
{
    /// <inheritdoc />
    public Document()
    {
        ExtraData = new HashSet<ExtraData>();
    }

    /// <inheritdoc />
    public Document(string key, IRobotRunEntry runEntry) : base(key, runEntry)
    {

        ExtraDataList = new HashSet<ExtraData>();
    }
    public virtual ISet<ExtraData> ExtraDataList { get; set; }
}

and map

    public DocumentMap() : EntityMap<ExtraData>
    {
        Table("DAT_DOCUMENTO_RC");

        Map(p => p.Code).Column("CODIGO").Nullable();
        Map(p => p.BeneficiaryUnityCode).Column("CODIGO_UNIDADE_BENEFICIARIO");
        Map(p => p.BeneficiaryCardCode).Column("CARTEIRA_BENEFICIARIO");
        References(p => p.Beneficiary).Column("ID_BENEFICIARIO").Nullable().Index("IDX_DOCUMENTO_RC_BENEFICIARIO");
        HasMany(p => p.Services).Cascade.AllDeleteOrphan().Fetch.Select().LazyLoad();
        HasMany(p => p.ExtraData) **????**;
    }

My question is: How i can map the relation between Document and ExtraData knowing i need to use a fixed value (RelatedEntityType) to join this tables?

A example query to illustrate the relation:

                    session.Query<ExtraData>()
                    .Where(p => p.RelatedEntityType == "DOCUMENTO"
                                && p.RelatedEntityId == 95)
                    .ToList();

Again, sorry for my poor english :)


Solution

  • You should be able to use "Where" on the HasMany mapping to achieve this filtering. Here's an example of what I mean:

    public class DocumentMap : ClassMap<Document>
    {
        public DocumentMap()
        {
            // ...
            HasMany(p => p.ExtraData)
                .Where(x => x.RelatedEntityType == "DOCUMENTO");
    
           // ...
         }
    }