English 中文(简体)
NHibernate - access the ID of an associated object without lazy loading the whole object
原标题:

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)

最佳回答

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.

问题回答

If you are using NHibernate 3.2 or later, you could use the following code to get the id of associated object without another roundtrip to database to load the whole object:

using NHibernate.Proxy;
...
object id = null;
if (obj.IsProxy()) // obj is the object you want to get its identifier.
{
    var proxy = obj as INHibernateProxy;
    if (proxy != null)
    {
        var li = proxy.HibernateLazyInitializer;
        if (li != null) 
            id = li.Identifier;
    }
}

You can use GetIdentifier method of Nhibernate session :

session.GetIdentifier(obj);




相关问题
nHibernate one-to-many inserts but doesnt update

Instead of getting into code, I have a simple question. Default behavior for a simple one-to-many is that it inserts the child record then updates the foreign key column with the parent key. Has ...

How Do I copy an existing nhibernate object as a new object?

I a persisted NHibernate object that I would like to repersist as a new entity. How do I get NHibernate to save this object as if it was a new? I am thinking I might create a session interceptor to ...

join across databases with nhibernate

I am trying to join two tables that reside in two different databases. Every time, I try to join I get the following error: An association from the table xxx refers to an unmapped class. If the ...

WPF - MVVM - NHibernate Validation

Im facing a bit of an issue when trying to validate a decimal property on domain object which is bound to a textbox on the view through the viewmodel. I am using NHibernate to decorate my property on ...

NHibernate Search in a List using ICriteria

I have my class X : public class ClassX { public virtual IList<ClassY> ListY { get; set; } ... } My ClassX mapping (using Fluent) ... HasMany<ClassX>(x => x.ListY ) ....

热门标签