-->
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.  [ 35 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: How to handle session in winforms?
PostPosted: Mon Jun 20, 2005 2:50 am 
Beginner
Beginner

Joined: Thu May 12, 2005 2:14 am
Posts: 33
Location: Sweden, Sk
Is there any best practise for using sessions in a winforms application? I ahve searched in the old forum and there are some posts, but im not sure which is the best solution.

Is it best to close the session diretly after I have loaded all my data and reconnect when I need to flush it? Or shall I hold the connection open until the usecase is closed.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 21, 2005 1:43 pm 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
Session management in Windows Applications is less "standard" than in Web Applications (because you can do what you want when you want).

A good practise is to make sessions short-living. As they are not "exception-proof", you should use it per-transaction...

But you can also decide to create a session for a longer (user-based) operation (required when you want to provide a high-level interactivity).

It depends of your application features and your goals (performance, scalability, ...)

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


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 22, 2005 4:05 am 
Beginner
Beginner

Joined: Thu May 12, 2005 2:14 am
Posts: 33
Location: Sweden, Sk
Hi

Thanks for your answer.

I have been playing a bit with it now and I think I have decided to make the sessions very short. Open, load all data and close it and reconnect when I need to persist some changes.


Top
 Profile  
 
 Post subject: Reconnecting?
PostPosted: Fri Jul 29, 2005 11:25 pm 
Newbie

Joined: Tue Jun 14, 2005 6:45 pm
Posts: 5
Just curious about your choice Patrick... why did you choose this strategy?

Also what are the Java guys doing? Or are there many Java Swing apps using Hibernate?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 29, 2005 3:33 pm 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
Hi,

I've been thinking on this same subject as well the last couple of days, and, in my opinion, sessions should be as shortlived as possible. Since, if you want to keep your application scalable, you should close your connections as from the moment you do not need them anymore.

However, I've heard that (N)Hibernate has problems with lazy loading of collections once you've closed your Session. How can we solve/workaround this?
What are the best practices for this situation ? IMHO, I cannot leave my session open, since, this could take to long before it is closed again.
then again, if I need some data out of this (lazy loaded) collection, how can I retrieve it , when my Session is already closed ?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 30, 2005 6:24 am 
Senior
Senior

Joined: Sat May 14, 2005 8:40 am
Posts: 130
whoami wrote:
What are the best practices for this situation ? IMHO, I cannot leave my session open, since, this could take to long before it is closed again.
then again, if I need some data out of this (lazy loaded) collection, how can I retrieve it , when my Session is already closed ?


Good question. I've experienced this as the most tricky aspect of using NHibernate and I don't really know of a perfect solution.
If you want lazy load to work after a session is closed you can open a new session and attach the object that has the lazy collections or properties (with ISession.Lock() and LockMode.None).

Imagine this scenario: a read-only list of orders with a closed session. When you want to edit an order, you start a new session and attach the order that is going to be edited. This way, the lazy properties like order.OrderLines or order.Customer work again. You keep the session open until you've finished the transaction (unit of work).

_________________
Cuyahoga


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 30, 2005 2:02 pm 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
That's a solution but, this means off course that:
1. the part of the application that's using the domain object must know that the collection is not loaded yet
2. the application also has to know that the object is not attached to an open session.

So, this means that -wherever you want to access the lazy loaded collection- you'll have to check if the collection hasn't been loaded yet and, you'll have to work with the nhibernate objects there.
I do not like this.

So, how do you know that you're lazy collection hasn't been loaded yet ?
In my opinion, you should not know that, it should be shielded for you.

Then again, how can I open attach this object to my collection nicely.
Maybe, you could do it in your POJO/POCO itself (i don't know, I've not that much experience with NHibernate yet).
Code:
public IList MyLazyCollection
{
      get
      {
             if( _lazyCollection == null )
            {
                  ISession sess = SessionFactory.OpenSession();
                 sess.Lock(this, LockMode.None);
            }
             return _lazyCollection;
      }
}

I don't know if this works (as I've said, I'm an NHibernate newbie), but, offcourse, the issue here is that you've NHibernate objects in your POCO.

I wonder if NHibernate will solve this issue in a future version ?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 31, 2005 3:57 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
Do you know how NHibernate can solve this problem ?

Because, it is very hard to transparently lazy load stuff once the session is closed; do you expect NHibernate to reOpen that session ? (that is definitively not something to do!)
And NHibernate will became less predictable (in term of executed SQL commands).

The example you give is not a very good solution because:
- NHibernate is used inside the entity (which is not a very good thing)
- It is hard to tell when this session will be closed...

Anyway, there is certainly something that can be done in NHibernate to help solving this issue; but we need to find and implement it...
And I am not sure that it is very needed because, most of the time, there is a good workaround that can be applied.

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


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 31, 2005 6:34 am 
Newbie

Joined: Thu Aug 25, 2005 5:05 am
Posts: 6
Not so sure this is the best practice, but the way Ive solved it is to create a session when the form that is supposed to use it is created, load the data I know Ill need in the constructor, and then disconnect it.

Then whenever I need detail information, usually due to the user selecting something from a list, I reconnect the session just long enough to show the detail information, then disconnect again.

From what I understand the difference between disconnecting and closing a session is just that disconnecting will keep more things in memory on the machine (the cache and other such things). For the SQL server its identical, isnt it?

/Dan


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 01, 2005 11:08 am 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
Well, I'm still a newbie in (N)Hibernate, but, why is a session so tightly coupled to a connection ?

As I see it -but I might be wrong- keeping an NHibernate ISession open, is not so bad. However, keeping the connection open that the ISession is using , is problematic.
So, why can't you just close the connection, but keep the Session open ?
In this way, the expensive database-connection is closed, and the session is still open. By doing this, the domain objects that have been loaded by a session, are still attached to this session, so lazy loading a collection of this domain object shouldn't be a problem.

But, as I've said before, I still have a lot to learn when it comes to (N)Hibernate, and this might be naive, silly, or whatever...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 02, 2005 7:53 am 
Senior
Senior

Joined: Sat May 14, 2005 8:40 am
Posts: 130
There is just a fundamental problem with long running sessions. The risk that the session contains stale data (for example, when data is modified by other users) gets bigger. At the moment, something goes wrong, your session is invalid and you have to get a new session to continue. In most cases this means that all changes are lost and you have to start again. Disconnection a session doesn't make this any different.

_________________
Cuyahoga


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 02, 2005 9:03 am 
Newbie

Joined: Thu Aug 25, 2005 5:05 am
Posts: 6
Ah yes, very true.

I forgot about that because its a non-issue in the program Im developing, in 99.9% of the cases anyways. People arent supposed to work on the same items at once, and I use optimistic concurrency to make sure they dont.

Although discarding the session and reconnecting the data when you need to isnt much better is it? Ill admit that I havent looked much on connecting objects to sessions again, but from what I understood the session wont update the object that way either?


Top
 Profile  
 
 Post subject: Lazy loading when session is closed
PostPosted: Mon Sep 05, 2005 1:41 pm 
Quote:
What are the best practices for this situation ? IMHO, I cannot leave my session open, since, this could take to long before it is closed again.
then again, if I need some data out of this (lazy loaded) collection, how can I retrieve it , when my Session is already closed ?


I came to a solution -i still don't know wether it's good or not- for this problem which does not relies on using NHibernate inside the entity.

The idea is the following:

In the entity, I hold a delegate which will be invoked if the lazy collection is not loaded. This delegated has to be set by the Data Access Layer when loading the entity. The method that is pointed by the delegate (which lives in the Data Access Layer) knows how to load the collection from the database and put it in the entity.

It will be easer to understand if you see the code. Supose you have a Customer entity which holds an Accounts collection.

In the entity:
Code:

// Loaded flag
private bool _areAccountsLoaded;

private IList _accounts;
private AccountsLoaderCallBack _loader;

public delegate void AccountsLoaderCallBack(Customer obj);

public IList Accounts
{
   get
   {
      // Manual lazy loading
      if (!_areAccountsLoaded)
      {
         _loader(this);
         _areAccountsLoaded = true;
      }
      return _accounts;
   }
   set
   {
      _accounts = value;
   }

public AccountsLoaderCallBack AccountsLoader
{
   set
   {
      _loader = value;
   }
}




In the Customer Data Access Layer:

Code:
public static Customer GetById(int id)
{
   // Open session...
   Customer obj = (Customer)session.Load(typeof(Entities.Customer),id);
   
   // Add the reference to the method that knows how to load the lazy collection manually
   obj.AccountsLoader = new Entities.Customer.AccountsLoaderCallBack(PopulateAccounts);

   // Close session...
   return obj;
}

public static void PopulateAccounts(Customer obj)
{
   // Open session again...

   // Load accounts. I'm not attaching the object to the session because that would load all the linked data of the entity. I just need the accounts.
   obj.Accounts = session.CreateQuery("from Account a where a.CustomerId = :parent")
   .SetInt32("parent", obj.Id).List();

   // Close session...
}


Also in you customer.hbm.xml you have to use access="field" for the accounts property, because if not, NHibernate will execute the code on initialization.

What do you think about this solution?

Mariano Szklanny
Buenos Aires, Argentina.


Top
  
 
 Post subject:
PostPosted: Tue Sep 06, 2005 7:47 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
A similar solution would be to create:

Code:
interface ICustomerCollectionsLoader
{
    bool IsAccountsLoaded(Customer);
    bool LoadAccounts(Customer);
}


It is better to let ICustomerCollectionsLoader say if a collection is loaded (using NHibernate)...

And then
Code:
ICustomerCollectionsLoader _loader;

// Safer !!!
public Customer(ICustomerCollectionsLoader loader)
{
    if(loader == null) throw new Exception("...");
    _loader = loader;
}

public IList Accounts
{
   get
   {
      // Manual lazy loading
      if (_loader.IsAccountsLoaded(this))
      {
         _loader.LoadAccounts(this);
         _areAccountsLoaded = true;
      }
      return _accounts;
   }
    set { ... }
}


But I am not sure that the implementation of PopulateAccounts() is the way to go...
Quote:
I'm not attaching the object to the session because that would load all the linked data of the entity. I just need the accounts.

You should do:
Code:
// attach the customer to this session (no communication with the database!)
session.Lock(customer, LockMode.None);
customer.Accounts.Count; // to load the collection

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


Top
 Profile  
 
 Post subject: Lazy loading when session is closed
PostPosted: Wed Sep 07, 2005 1:46 pm 
Newbie

Joined: Mon Sep 05, 2005 1:44 pm
Posts: 1
Thanks a lot KPixel for your anser! It's seems to me to be a better solution. Now I see I had a wrong idea about attaching objects to the session...

May I ask you something? why do you say it's safer to use a constructor like

Quote:
public Customer(ICustomerCollectionsLoader loader) {...}


?
Anyway I'll have to supply an default constructor for NHibernate to work, won't I?

And as regards the implementation of
Code:
ICustomerCollectionsLoader.LoadAccounts(Customer);


I tried to use NHibernateUtil.Initialize(myCustomer.Accounts) but that will enter in an infinite loop since I will be accessing Customer.Accounts property! And the same would happen with the implementation of PopulateAccounts() you suggested! Any ideas about this?

Thanks again!
Mariano


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 35 posts ]  Go to page 1, 2, 3  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.