1

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?

Kevin Albrecht
  • 6,974
  • 7
  • 44
  • 56

3 Answers3

1

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
  • 6,330
  • 3
  • 33
  • 52
  • 1
    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 Dec 08 '09 at 20:40
  • That is sort of what I expected. – Kevin Albrecht Dec 08 '09 at 20:57
1

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
  • 1,127
  • 8
  • 14
  • 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 Dec 09 '09 at 01:18
  • 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 Dec 09 '09 at 02:45
0

Make AnimalID and OwnerID a composite primary key.

Chris
  • 27,596
  • 25
  • 124
  • 225
  • 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 Dec 07 '09 at 17:21