views:

345

answers:

1

I have two associated business objects - A and B. the association is (A->B)many-to-one, with B.Id a foreign key in A (so A has A.B_id in the DB).

I'm using lazy=true and solved most of my problems, however in A's ToString I want to print also A.B.Id, which I should have without further trips to the DB. but accessing A.B activates the proxy, and since this isn't in the context of an open session, throws an exception.

one easy but ugly solution would be to have A.B_id property. but that's part of the stuff we were trying to avoid in the first place. any "organic" way to do this? :) thanks!


UPDATE: just read about caching and Session.Get vs. Session.Load. before I only new that one throws an exception if the object doesn't exist (Session.Load), and the other returns a null object (Session.Get). after reading about caching here, it's clear that Session.Load returns a proxy to the object, and only lazily fetches it when a property other than the ID is accessed, which is very much like what I need from associations! for now I added the separate object ids (added B_Id to A so I can access it as A.B_Id instead of using A.B.Id)

+2  A: 

For the exact same reason I have used explicit A.B-ID properties for all my many-to-one relationships. I do not see this as a quick and dirty solution as it provides a solution to this problem and also lot of flexibility is the saving-updating area i.e. I do not need to fetch from the database the B object just to assign it to A in order to create the association when I have the B_ID in a query string or somewhere else.

My mapping files useually look like this:

<property name="CreatorID" column="CreatorID" type="Int32" not-null="true" />
<many-to-one name="Creator" column="CreatorID" class="SystemUser" insert="false" update="false" cascade="none" />

As you can see one of the 2 properties has to be read only to avoid having NHibernate sending 2 times this column to the database when inserts or updatas are happening. The above makes as read only (by using the insert="false" update="false" attributes) the many-to-one but you can instead have as read only the CreatorID property if you like.

Having only the many-to-one you do not have a property in your entity class A to hold the B.ID value. The only way to get it is by accessing the B object which will trigger the proxy and it will fire a query to the database (if it is not loaded in the session already).

I will be happy to hear any other option that provides a solution and offers the same kind of flexibility.

tolism7
I still wish this could be done using just A.B.Id - I don't like the duplicate data - I had these properties and *removed* them... I will investigate the matter further but for now this is what I'll do. thanks!
Yonatan Karni