2

Is it possible to navigate through the key-many-to-one associations of a composite-id in Nhibernate?

I have a few (legacy) tables that I mapped with the following settings:

<class name="StructureUser">
    <composite-id>
        <key-many-to-one name="Structure" class="Structure" column="STRUKTUR_ID" />
        <key-many-to-one name="User" class="User" column="USERID" />
    </composite-id>
    ...
</class>

<class name="Structure">
    <id name="Id" column="id" type="Int32" >
        <generator class="native"/>
    </id>
    <property name="Low" column="low" type="Int32" />
    ...
</class>

I want to access the "Low" property of Structure through the StructureUser class in a query. I tried every usage of the Criteria API I could think of but always an error. Here are two of the queries I tried:

ICriteria crit1 = Session.CreateCriteria(typeof(StructureUser))
    .CreateAlias("Structure", "struc")
    .Add(Restrictions.Le("struc.Low", 123));

ICriteria crit2 = Session.CreateCriteria(typeof(StructureUser))
    .Add(Restrictions.Le("Structure.Low", 123));

The error in crit1 comes from the database and says, that "struc_1.Low is not valid in this context", because NHibernate doesn't generate the join needed for the restriction in the sql command. The error in crit2 comes from NHibernate, telling me that it can't access the "Structure.Low" property on StructureUser.

I got around this problem by declaring the composite-id with key-property elements and declaring the relationships with normal many-to-one elements.

Is there another solution to this problem?

g .
  • 8,110
  • 5
  • 38
  • 48
Matthias Schippling
  • 2,923
  • 1
  • 18
  • 29

2 Answers2

0

have you tried

ICriteria crit1 = Session.CreateCriteria(typeof(StructureUser))
    .CreateCriteria("Structure", "struc")
    .Add(Restrictions.Le("struc.Low", 123));
Jaguar
  • 5,929
  • 34
  • 48
  • I don't remember :). Have to try it next week when I'm back at work. – Matthias Schippling Nov 12 '09 at 13:48
  • Ok, it took me more than a year, but I finally tested it. Unfortunately, your suggestion doesn't work either :(. – Matthias Schippling Nov 25 '10 at 10:27
  • you could also try to create the alias with .CreateAlias("id.Structure", "struc") note the lower case 'id' which is reserved for the abstract id property. On an other note, i've found that for Composite-Id's the Component class route is way easier to work with, but is more verbose on all levels – Jaguar Nov 25 '10 at 12:48
0

I had a similar problem.

As the original poster said, you need to add a many-to-one relationship on the element from the composite key you want to alias and you need to set the properties "insert" and "update" to "false".

Then you can keep it in the composite-id, you don't need to change it into a key-property element.

<class name="StructureUser">
<composite-id>
    <key-many-to-one name="Structure" class="Structure" column="STRUKTUR_ID" />
    <key-many-to-one name="User" class="User" column="USERID" />
</composite-id>

<many-to-one name="Structure" class="Structure" column="STRUKTUR_ID" insert="false" update="false" />

...