-->
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.  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Winform lazy loading with seperate data layer.
PostPosted: Mon Sep 12, 2005 2:30 pm 
Here is an example of my problem, I have a Customer class witch has the following method which is mapped to use lazy loading

Code:
IList Orders
{
         get
            {
            if(orders == null)
            {      
               orders = new ArrayList();
            }
            return orders;         
         }   
}


I have a "DBManager" class with the following code that will return a list of a certain object type, in this case I call it with the Customer Type

Code:
static public IList getList(Type _type)
      {
         IList objList = null;
         ITransaction tx = null;
         ISession session = null;
         try
         {
            session = factory.OpenSession();
            tx = session.BeginTransaction();
            objList = session.CreateCriteria(_type).List();
            
            session.Close();
         }
         catch (Exception ex)
         {
            if(tx != null)
            {
               tx.Rollback();
            }
            session.Close();
         }
         return objList;
      }


Ok, so I am able to access the list of customers from the winform gui by calling DBManager.getList(typeof(Customer)).

When I iterate through this list though and call customer.Orders I get the following exception:

An unhandled exception of type 'NHibernate.LazyInitializationException' occurred in nhibernate.dll

Additional information: Failed to lazily initialize a collection - no session


My question is... what is the "best" way of dealing with this. I have read through the forums and haven't identified an approach that seems like a best practice(e.g sticking hibernate code in the Customer class itself to call initialize()).

I can get around this particular issue by not lazy loading, but the app has about 30 tables and if I disable lazy loading it just slows to an absolute crawl.


Top
  
 
 Post subject:
PostPosted: Mon Sep 12, 2005 2:52 pm 
Newbie

Joined: Thu Sep 08, 2005 12:15 pm
Posts: 17
In my web app I open the session in the BeginRequest Event and I close it in the EndRequest. I do this stuff in an httpModule like its done in the Cuyahoga project.
http://www.martijnboland.com/cuyahoga/


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 12, 2005 3:14 pm 
Newbie

Joined: Thu Sep 08, 2005 12:15 pm
Posts: 17
sorry I didn't realize that you were talking about a windows app.


Top
 Profile  
 
 Post subject: thanks though
PostPosted: Mon Sep 12, 2005 4:32 pm 
Simon, no problem, this app will be ported to a web app sometime in the next few months so that is useful.

Along the lines of that, has anyone ran into problems with opening the session on formLoad and closing the session when a form window is closed? I know this keeps the session open basically indefinitely, does anyone use this approach with success?


Top
  
 
 Post subject:
PostPosted: Mon Sep 12, 2005 8:58 pm 
Newbie

Joined: Tue Jun 07, 2005 4:13 pm
Posts: 2
Location: Orillia, Ontario, Canada
That would be an approach worth trying, just use the session.Disconnect() at the end of the form load event. Then on the form closing event using the same session object reconnect do any changes required saving or updating and then close the session.
From my understanding using session.Disconnect closes the ado connection underneath but still leaves the session object (and it's loaded relations) intact.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 13, 2005 1:29 am 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
This will point you in the right direction
http://www.hibernate.org/168.html


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 03, 2005 6:44 pm 
Newbie

Joined: Sat Aug 20, 2005 10:39 am
Posts: 12
Location: Brazil
I am with the same problem between my WinForms application, a Webservice and the DAO.

How you it decided this?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 04, 2005 12:06 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
For windows forms, trying to disconnect the session on form load (and reconnect on form close) has the same problem -- if you have any lazy loading, you'll get

NHibernate.LazyInitializationException: Failed to lazily initialize a collection - session is disconnected

Shouldn't the proxies reconnect/disconnect as needed? If this is deemed not the responsibility of the proxies, perhaps a pair of events on the session could be exposed (e.g. "LazyLoading", "LazyLoaded") where we could do the reconnect/disconnect ourselves ...


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 06, 2005 10:49 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
What I do is:
Code:
try
{
    myGateway.OpenSession();
    // Load / Save / use entities (=> lazy load)
    // You may use myGateway.AttachEntity(entity) (call Lock()...)
}
finally
{
    myGateway.CloseSession(); // Commit + Close
}


This means that I do all the initialization work (requiring lazy loading) in one place...

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 10:31 am 
Beginner
Beginner

Joined: Mon Oct 03, 2005 4:59 am
Posts: 26
Location: Cambridge, UK
I'd think that making a session on Form_Load() and closing it on Unload() would be dangerous, because NHibernate sessions do not recover from exceptions. If any of the user's interactions on the form cause an NHibernate exception, your session is no good any more, and the user has to close the form and open it again to continue working.

If it were me (it's not; currently all my NHibernate usage is from web pages), I'd think about making sessions last for the duration of each event handler on a form.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 10:50 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
I too think that opening a session only for a duration of one event is the way to go.


Top
 Profile  
 
 Post subject: newbee here having lazy problems too
PostPosted: Mon Nov 07, 2005 11:49 am 
"If it were me (it's not; currently all my NHibernate usage is from web pages), I'd think about making sessions last for the duration of each event handler on a form."

How would you do that.
:roll:


Top
  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 11:51 am 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Maybe I'm not understanding the problem ...

Say you've retrieved several entities and displayed them in a windows form. The entities are lazy-loaded, so collections aren't loaded, etc. You've opened a session, retrieved these entities, and closed the session.

Now the user clicks on something which accesses a lazy-loaded property. Is it the responsibility of the UI to check if this property needs loading? How is that even possible with lazy-loading? I thought the whole point of lazy loading was for it to happen "behind-the-scenes", as needed. The code submitting the initial query and the other UI logic shouldn't know or care if lazy loading is occuring or not. Am I expecting too much here?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 12:31 pm 
Beginner
Beginner

Joined: Mon Oct 03, 2005 4:59 am
Posts: 26
Location: Cambridge, UK
Quote:
The code submitting the initial query and the other UI logic shouldn't know or care if lazy loading is occuring or not. Am I expecting too much here?

No, that sounds right. The catch is, in order for lazy loading to work, the entity class in question needs to be attached to a session. Suppose Parent is an entity class with a lazy collection called Children. Then this will not work (code written in browser, should be treated as pseudocode):
Code:
public class PersonForm : System.Windows.Forms.Form
{
    private Person m_person;

    public PersonForm( int id )
    {
        ISession session = sessionfactory.OpenSession();
        m_person = session.Get( typeof( Person ),  id );
        session.Close();
    }

    private void PersonForm_Load( object sender, EventArgs e )
    {
        textPersonName.Text = m_person.Name;
    }

    private void Button1_Click( object sender, EventArgs e )
    {
        StringBuilder children = new StringBuilder();
        children.Append( "This person's children are: \n" );
        foreach( object o in m_parent.Children )    /// Produces lazy loading exception
        {
            children.Append( ((Child) o).Name + "\n" );
        }
        textPersonChildren.Text = children.ToString();
    }
}


But this code will work (ditto):

Code:
public class PersonForm : System.Windows.Forms.Form
{
    private Person m_person;

    public PersonForm( int id )
    {
        ISession session = sessionfactory.OpenSession();
        m_person = session.Get( typeof( Person ),  id );
        session.Close();
    }

    private void PersonForm_Load( object sender, EventArgs e )
    {
        textPersonName.Text = m_person.Name;
    }

    private void Button1_Click( object sender, EventArgs e )
    {
        ISession session = sessionfactory.OpenSession();
        session.SaveOrUpdate( m_parent );

        StringBuilder children = new StringBuilder();
        children.Append( "This person's children are: \n" );
        foreach( object o in m_parent.Children )    /// no exception!
        {
            children.Append( ((Child) o).Name + "\n" );
        }
        textPersonChildren.Text = children.ToString();

        session.Close();
    }
}


Again, I've not compiled or tested this code, but I think that's the way it works.


Top
 Profile  
 
 Post subject: Session Facade
PostPosted: Tue Nov 08, 2005 4:03 am 
there is no standard way how to handling session in winform application. Keep session as short as possible for every single method make your application open an close connection many times and takes a lot of resources. My suggestion is using Session Facade. For example if using short session for every method it will become something like this from winform app.

1.open session
2.update record
3.close session
4.open session
5.list updated record
6.close session

For session facade it will become

1. open session
2. update record
3. flush session
4. list updated record
5. close session


Top
  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 21 posts ]  Go to page 1, 2  Next

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.