Search code examples
nhibernatecomposite-id

nhibernate composite-id with not existing key-many-to-one record


i have old legacy DB which has dead links in their tables. I have class mapped in nhibernate like this:

<class name="Visible" table="table_visible">
    <composite-id>
        <key-many-to-one column="object_id" name="ObjectA" />
        <key-many-to-one column="sub_object_id" name="SubObject" />
    </composite-id>
    <property column="visible" name="VisibleRow" />
</class>

and:

public class Visible
{
    public virtual ObjectAClass ObjectA { get; set; }
    public virtual SubObjectClass SubObject { get; set; }
    public virtual bool VisibleRow { get; set; }

    public override bool Equals(object obj)
    {
        var other = ((Visible)obj);
        return this.ObjectA.Equals(other.ObjectA) && this.SubObject.Equals(other.SubObject);
    }

    public override int GetHashCode()
    {
        return this.ObjectA.GetHashCode() + (this.SubObject != null? this.SubObject.GetHashCode(): 0);
    }
}

Now all works fine when all joins in database are correct, but when i find such sub_object_id which doesnt have entity, nhibernate throws me error

No row with the given identifier exists:[SubObject#123]

Is there a way to map composite key so that when its subentity is not found, the whole entity wouldnt be loaded (like with inner join)?

NHibernate v2.0.50727


Solution

  • Following Daniel Schilling idea of fetch Visible entities with a where exists sub-query, found that there is loader element available in mappings.

    <class name="ObjectA" table="table_object">
        .........   
        <set name="VisibleList" cascade="all" lazy="false" inverse="true">
            <key column="object_id" />
            <one-to-many class="Visible" />
            <loader query-ref="valid_entities"/>
        </set>
    
    </class>
    <sql-query name="valid_entities">
        <load-collection alias="v" role="ObjectA.VisibleList"/>
        SELECT {v.*}
        FROM table_visible v
        INNER JOIN table_sub_entities e ON e.sub_entity_id=v.sub_entity_id
        WHERE v.object_id=?
    </sql-query>
    

    And nothing else needed to be changed.