views:

239

answers:

3

I have the following definitions for the Animal and Dog types. Note that the ID for the object is the AnimalID:

<class name="Animal" table="Animals">
    <id name="Id" type="System.Int32" column="AnimalID">
        <generator class="identity" />
    </id>
    <property name="IsBig" column="IsBig" type="System.Bool" not-null="true" />  
</class>

<joined-subclass name="Dog" table="Dogs" extends="Animal">
    <key column="AnimalID" />
    <property name="OwnerID" column="OwnerID" type="System.Int32" non-null="true" />
    <property name="IsStrong" column="IsStrong" type="System.Bool" non-null="true" />
</joined-subclass>

Let's say I have the following information in my database:

in table Animals:

AnimalID    IsBig
--------    -----
10          True

in table Dogs:

AnimalID    OwnerID    IsStrong
--------    -------    --------
10          1          True
10          2          False

First, I query for the Dog where OwnerID = 1. In the same session, I query for the Dog where OwnerID = 2. Because of NHibernate's Session cache, the second query returns a Dog object where OwnerID = 1 and IsStrong = True, where it should return a Dog object where OwnerID = 2 and IsStrong = False.

NHibernate automatically caches objects by their ID (primary key) column, so requesting the Dog the second time ends up retrieving an object with the same key. I can solve this problem by calling ISession.Evict() on the object, but that seems like a hack.

Any better suggestions?

A: 

Make AnimalID and OwnerID a composite primary key.

Chris
That will not work because the Dog is joined to it's parent class by the AnimalID column. If Dog defined (AnimalID, OwnerID) as a composite key, it could not be joined to the Animal class by AnimalID.
Kevin Albrecht
True, this won't work.
Alex Yakunin
+1  A: 

You must ensure you're using different keys for different instances. In your case you're actually violating this rule: Dogs table exposes parts of two instances sharing the same key.

So Dogs.AnimalID must be marked as primary key, but in your case it isn't. If it would be marked as PK, you couldn't get such content at all.

Alex Yakunin
So from the point of NH there is a single instance of Animal in this case: the one having AnimalID==10. But your database schema actually allows you to store multiple rows for this instance in Dogs table - just because there is no primary key (although it must be there).
Alex Yakunin
That is sort of what I expected.
Kevin Albrecht
+1  A: 

With respect, the question you should be asking is "how do I model this correctly?"

Your Dogs table says that dog 10 is owned by owner 1 and is strong, but, at the same time, dog 10 is owned by owner 2 and is NOT strong.

Somehow, I don't think that's what you meant.

If you'll explain in more detail what you're trying to model, perhaps we can make some suggestions.

kem
Since this seems like a different question, I created a different one here:http://stackoverflow.com/questions/1871043/nhibernate-how-to-correctly-model-this-schema
Kevin Albrecht
ok...that one's not much clearer to me, i'm afraid. It seems like you're combining two concepts here: 1) mapping of class hierarchies, and 2) many-to-many relationships.
kem