-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Casting with lazy loaded proxies
PostPosted: Tue May 23, 2006 12:37 pm 
Expert
Expert

Joined: Tue Aug 23, 2005 5:52 am
Posts: 335
Perhaps someone's solved this problem before...

I have an abstract Job class which has been derived as the concrete classes ManualJob and AutomaticJob. I need to be able to cast Job to it's subclasses so I've done my mapping using the interfaces IJob, IManualJob and IAutomaticJob - all this is working fine.

The problem is that the Job class also has a ParentJob property of type IJob, but I need to be able to find out at runtime which sub-type of Job the ParentJob actually contains. Using job.ParentJob.GetType() returns the type of the proxy (which is no good), and using NHibernate.Proxy.NHibernateProxyHelper.GetClass(obj) always returns the type of the abstract Job class rather than the actual concrete subclass.

Is there a way to get the type of a lazy loaded proxy that will consistently return the correct type? I would have thought the ProxyHelper.GetClass method would do it, so maybe it's a bug?

Anyone got any thoughts?

Symon.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 23, 2006 1:45 pm 
Expert
Expert

Joined: Tue Aug 23, 2005 5:52 am
Posts: 335
As an observation, I notice that the ProxyHelper.GetClass method uses the LazyInitializer.PersistentClass property, which always returns the type specified when the LazyInitializer was created.

I'm assuming that since in my particular case IJob.ParentJob is of type IJob that the LazyInitializer is instantiated withe the PersistentClass of type Job, so that's what it will always return.

The problem is that once the object has been loaded the private member _target refers to the actual type, but this is not accessible. It looks like I could do something with the LazyInitializer.GetImplementation method to access the actual target of the proxy, but I'm not sure how to approach this...on the other hand it looks like changing the LazyInitializer.PersistentClass getter to return the _persistentClass type if it's uninitialized and return _target.GetClass() if it is initialized would be the easiest way. Would that be a mistake?

Symon.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 23, 2006 4:22 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
I think you're right and it is a bug. Please open a JIRA issue.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 23, 2006 5:34 pm 
Expert
Expert

Joined: Tue Aug 23, 2005 5:52 am
Posts: 335
Done.

http://jira.nhibernate.org/browse/NH-612

Symon.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 23, 2006 6:11 pm 
Expert
Expert

Joined: Tue Aug 23, 2005 5:52 am
Posts: 335
Sergey,

You might want to cancel that Jira entry - NHibernateUtil.GetClass() does what I was expecting NHibernate.NHibernateProxyHelper.GetClass() to do. It forces loading of the object so that the actual class can be obtained. Hopefully others will be able to use this info.

Cheers,

Symon.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 21, 2006 5:08 pm 
Newbie

Joined: Fri May 13, 2005 11:14 am
Posts: 18
I am running into the same issue and am trying to figure out how to actually cast the collection object.

All my classes Lazy Load. I retrieve an object that contains a collection from the database. I iterate through the collection and the objects are of INHibernateProxy of an Interface. I want to try to figure out what sub-class type they are of and cast accordingly.

Before, I was able to just check the type of the object:

if (persistedOption is FacilityFixedRateOption)
{
// do something
((FacilityFixedRateOption) persistedOption).FixedRate
}

but this never works. It doesn't match when I check the type, which is always INHibernateProxy.

I can get the correct type with this call:

Type type = NHibernateUtil.GetClass(persistedOption);

but I still have a problem casting. Below is how I figured out to cast. Is there a better way?



RateOptionGroup group = repository.RetrieveRateOptionGroup(groupId);
IFacilityRateOption persistedOption = group.Options[0] as IFacilityRateOption;

if (persistedOption is INHibernateProxy)
{
Type type = NHibernateUtil.GetClass(persistedOption);
persistedOption =
NHibernateProxyHelper.GetLazyInitializer((INHibernateProxy) persistedOption).GetImplementation() as
FacilityFixedRateOption;
}


Below are the mappings.

Thanks in advance,
Jamie





Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
   <class name="Ais.Sentry.Domain.Securities.Loans.RateOptionGroup, Domain" table="rate_option_groups">
      <id name="Id" column="id" type="Int32" unsaved-value="0" >
         <generator class="identity" />
      </id>   
      <property name="Name" column="name" type="String" not-null="true" />   
      
      <bag name="Options" table="rate_option_group_values" lazy="true" cascade="all">
         <key column="group_id"/>
         <many-to-many class="Ais.Sentry.Domain.Securities.Loans.IFacilityRateOption, Domain"  column="rate_option_id" />   
      </bag>   
   </class>
</hibernate-mapping>




Code:
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
   <class name="Ais.Sentry.Domain.Securities.Loans.IFacilityRateOption, Domain" table="facility_rate_options">
      <id name="Id" column="id" type="Int32" unsaved-value="0" >
            <generator class="identity" />
      </id>
      <discriminator column="discriminator" type="String" />

      <property name="Description" column="description" type="String"/>
      <property name="PayConvention" column="pay_convention_id" type="Ais.Sentry.Domain.Calendars.PaymentConvention, Domain" not-null="true" />
    <property name="IsAutoGenerated" column="is_auto_generated" type="Boolean" not-null="false"/>
   
    <subclass name="Ais.Sentry.Domain.Securities.Loans.LoanRateOption, Domain" discriminator-value="LoanRateOption" >
         <many-to-one name="facility" class="Ais.Sentry.Domain.Securities.Loans.CreditFacility, Domain" column="financial_security_id" access="field"/>
         
         <subclass name="Ais.Sentry.Domain.Securities.Loans.FacilityFixedRateOption, Domain" discriminator-value="FixedRateOption" >
            <property name="fixedRate" column="fixed_rate" type="Decimal(12,8)"  access="field"/>

        <many-to-one name="fixedRateSchedule" class="Ais.Sentry.Domain.Collections.RateSchedule, Domain" column="rate_schedule_id" cascade="all" access="field"/>

         
         </subclass>
         
         <subclass name="Ais.Sentry.Domain.Securities.Loans.FacilityFloatingRateOption, Domain" discriminator-value="FloatingRateOption" >
            <property name="spread" column="spread" type="Decimal(12,8)" access="field"/>
            <property name="initialCouponRate" column ="initial_coupon_rate" type="Decimal(12,8)" access="field"/>
            
         </subclass>
      </subclass>
         
   </class>
</hibernate-mapping>


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.