简体   繁体   中英

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

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.

<key-many-to-one column="sub_object_id" name="SubObject" not-found="ignore" />

... may be helpful. From the NHibernate Documentation ...

ignore will treat a missing row as a null association

Please be aware of the performance penalty associated with using this option. Whenever NHibernate fetches a Visible entity, it will also have to fetch SubObject . If you don't go ahead and fetch it in your query, this means that NHibernate will be issuing lots of lazy loads.

This doesn't meet your "when its sub-entity is not found, the whole entity wouldn't be loaded" goal. Instead NHibernate would give you an entity with a null sub-entity. If you want that inner-join-like behavior, then I think you would need to fetch your Visible entities with a where exists sub-query to make sure the SubObject actually exists.

The best option would be to fix the data in the database and add a foreign key constraint.

I just ran across this: Relations with not-found="ignore" . I promise I'm not copying Ricci's content - I'm writing this from my own experience.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM