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.  [ 34 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: WinForms Framework
PostPosted: Thu Jun 14, 2007 6:06 pm 
Regular
Regular

Joined: Fri Jan 27, 2006 2:32 pm
Posts: 102
Location: California, USA
I have developed an application. While the application itself wouldn't be of much interest to anyone, the "framework" that it is built on might.

It is a WinForms application. Would there be any interest in having an Open Source WinForms framework for NHibernate?

It is an MDI style application, with each child form getting its own NHibernate session. This sometimes leads to cross session issues when an object is loaded by one form but needs to be passed to another form.

So the question boils down to this: would a framework be even helpful to others? Or, would it be a waste because it would take too much time to become familiar with / not generic enough to use for a variety of applications.

Open to feedback....


Last edited by pelton on Fri Jun 15, 2007 1:49 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 15, 2007 3:11 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Hello,

I too have a couple of WinForms application based on NHibernate and judging by the amount of threads related to using NHIbernate in WinForms apps, I do think that a framework would be helpful or at the least, interesting.

But I do not agree with the approach of 1 session per form. I believe you should use 1 session per request: one request fetches the data, another request updates the data, and so on... To me, the only correct way is to use sessions with a very short lifespan and using your entities in a detached manner (= reattaching them when you need to initialize collections, update the entity itself, ...).

I know, there's a lot of trouble handling the lazy initializations but with a lot of love and dedication, it can work.

Anyway, all I wanted to say was: even if I do not agree with the idea of 1 session per form, it might still be of interest to others. And after all, who's to say my approach is the best ?

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 15, 2007 6:30 am 
Senior
Senior

Joined: Sat May 14, 2005 8:40 am
Posts: 130
There can't be enough samples. Unfortunately when using WinForms, NHibernate can be a real dog if you don't know exactly what you're doing.

In a real-world project I've tried to overcome the issues with decoupling the session management from the UI (views). It was an MVC style application where every controller has its own associated Session and one or more views.
The trick that worked very well here is to have only one active controller with an open session and to have a notification mechanism when a controller is activated or deactivated. On activation you have the choice to either open a new session (requires you to refresh the data) or to reconnect the existing associated session (in scenarios without concurrency risks).
A benefit of this approach is that the session management is the same for every style of UI, whether it be a SDI interface, MDI interface or an interface with lots of separate windows.
Unfortunately I can't share the code though.

_________________
Cuyahoga


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 18, 2007 12:40 pm 
Regular
Regular

Joined: Fri Jan 27, 2006 2:32 pm
Posts: 102
Location: California, USA
WinForms is so flexible, perhaps a framework is too constricting.

There seems to be a lot of interest in a "proper" way to handle sessions and maybe even databinding.

But, a framework would begin to force a particular approach. Or it would be so generic that it really wouldn't be a framework at all. Just a few helper classes.

So, as a sample it might have some value, but I guess it wouldn't be used as a starting point for new projects.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 19, 2007 4:33 pm 
Newbie

Joined: Tue Mar 21, 2006 3:11 pm
Posts: 10
I created my own little mini-framework of classes to help with developing with NHibernate in WinForms. I did something similar to the one session per form approach.

Basically, I created two base forms to help deal with sessions. The first base Form was the SessionAwareForm. This takes care of accessing some helper classes to retrieve a ISession that it is used while the form is open and then closed when the form closes. The other form was the SharedSessionForm that would receive an ISession from a parent form during construction. This allowed me to have forms that shared an ISession with another form. Very helpful with popups that perform work and may need to participate in a Transaction in the parent form.

Lately, though I have begun to play around with creating a Component that could be dropped onto the form and used to manage the session. This would free me from having to extend the Session aware base classes and could be used anywhere (with proper config). I haven't gotten very far yet due to a lack of time.

Just my 2 cents.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 20, 2007 11:42 am 
Regular
Regular

Joined: Fri Jan 27, 2006 2:32 pm
Posts: 102
Location: California, USA
flahan wrote:
The first base Form was the SessionAwareForm. This takes care of accessing some helper classes to retrieve a ISession that it is used while the form is open and then closed when the form closes.


So, your UI has a reference to NH? I tried to isolate NH from my application as much as possible. I think some people do even more than I do. What I have is a Data assembly that references NH. Then, my UI uses my Data assembly. My WinForm objects use a SessionManager that contains all of the ISession objects. So, the form itself only keeps track of its Session ID (an int). It then calls methods on SessionManager to Open, Close, Load, Save, etc. objects. The only real NH stuff in my UI layer is I use a lot of HQL strings. The actual searching is performed in the Data assembly.

flahan wrote:
The other form was the SharedSessionForm that would receive an ISession from a parent form during construction. This allowed me to have forms that shared an ISession with another form. Very helpful with popups that perform work and may need to participate in a Transaction in the parent form.


Yes, I had to do something similar for the same reasons.

flahan wrote:
Lately, though I have begun to play around with creating a Component that could be dropped onto the form and used to manage the session. This would free me from having to extend the Session aware base classes and could be used anywhere (with proper config).


Do you have fairly small projects? I'm curious why you don't want to try to seperate NH from your UI. Is it just preference?

It seems like all the advice I've seen is to try to keep NH isolated to a Data layer and away from your Business Objects and UI as much as possible.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 20, 2007 9:27 pm 
Newbie

Joined: Tue Mar 21, 2006 3:11 pm
Posts: 10
I do have a separate data layer, and for the most part the forms don't really deal with NH. The reason, I set up the base form was so that I could isolate the NH interaction to a single base class and then subclasses wouldn't have to deal with it very much. For example, when a form closes, clean up of the ISession is taken care of automatically.

I have a Session Manger class also, but use a string as the id. The base form retrieves the ISession when it is requested by a subclass. The subclass then uses it to initialize DAO classes and business logic classes. Where possible I try to move complex/reusable/transaction oriented logic to the business/service classes. There is some transaction management in the forms, but I try to avoid doing it. All query related activity is in the DAO classes and I expose some QueryByExample type objects to help DAO clients build complex queries.

I have around 90 to a 100 tables in my application, so keeping things easy to manage is very important. Originally, I tried to isolate my UI from NH, but the hoops I had to jump through to get things to work became too cumbersome. I came up with this approach as a compromise between maintaining the separation between data access and UI layers and keeping the process easy to manage (and reuse).


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 21, 2007 11:48 am 
Regular
Regular

Joined: Fri Jan 27, 2006 2:32 pm
Posts: 102
Location: California, USA
flahan wrote:
I do have a separate data layer, and for the most part the forms don't really deal with NH. The reason, I set up the base form was so that I could isolate the NH interaction to a single base class and then subclasses wouldn't have to deal with it very much. For example, when a form closes, clean up of the ISession is taken care of automatically.

I have a Session Manger class also, but use a string as the id. The base form retrieves the ISession when it is requested by a subclass. The subclass then uses it to initialize DAO classes and business logic classes. Where possible I try to move complex/reusable/transaction oriented logic to the business/service classes. There is some transaction management in the forms, but I try to avoid doing it. All query related activity is in the DAO classes and I expose some QueryByExample type objects to help DAO clients build complex queries.

I have around 90 to a 100 tables in my application, so keeping things easy to manage is very important. Originally, I tried to isolate my UI from NH, but the hoops I had to jump through to get things to work became too cumbersome. I came up with this approach as a compromise between maintaining the separation between data access and UI layers and keeping the process easy to manage (and reuse).


Your application is larger than mine, at about 30 entities. And so probably also you have more complexities.

So far I have been succesful in keeping NH out of my UI by using only HQL in the UI. Searching is done by either HQL or by example.

I'm a little surprised at how many similarities there are in our approaches. I guess that makes me feel better that I'm not total rogue in my approach.

You have given me pause to re-think about posting my "framework" as open source. Perhaps no one will use it as-is, but it could provide ideas - either "avoid my mistake" or "hey that's cool".


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 24, 2007 9:35 am 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
@pelton
If you keep NHibernate out of your UI, where do you initiate transactions then ?
Do you have a separate Service Layer ?

If not .... where do you start / commit transactions ? Since, IMHO it is the client (which is in this case the UI) that knows the context of the use-case, and it is the client that should start / commit / rollback the transaction.

@xasp
Why is the 'session-per-form' a bad approach ?
If you use a 'session-per-request', you'll have to re-attach the entities which were loaded by session 'A' to session 'B' when you're going to save them. Then, this also means that you'll have to re-load them from the DB first to know whether an entity needs to be inserted or updated , and if it is necessary to update one.
What's the problem with the 'one-session-per-form', if you disconnect your session from the DBConnection whenever you do not need to communicate with the DB for a while ?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 24, 2007 10:01 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Well,

First of all: because the NHibernate documentation clearly states that the Session-object is supposed to be short-lived and it's lifespan must be kept as short as possible. This doesn't match the idea of one-session-per-form.

But also because, when multiple forms have a reference to the same object (f.e. because you have an eventing mechanism between you forms), how are you going manage this? Especially when one form has an object that originally came from another form and must be saved.

And last but not least: as long as the session lives, it will not only keep the objects in memory but will also check the state of each one of those objects when a Flush() occurs. This might be time-consuming when you loaded a lot of entities (f.e. when filling a grid).

Quote:
Then, this also means that you'll have to re-load them from the DB first to know whether an entity needs to be inserted or updated, and if it is necessary to update one.

When re-attaching an entity, there isn't necessarily a roundtrip to the database. You can just Lock() an entity, modify it and then Flush() the session. The Lock() won't refetch the entity.

I could agree with the idea of a one-session-per-form approach when the forms' lifespan is supposed to be short and there can only be one form open at a time. But generally, I do not think this is the right approach.

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 24, 2007 1:45 pm 
Newbie

Joined: Sat Jun 09, 2007 9:40 am
Posts: 11
Quote:
But I do not agree with the approach of 1 session per form. I believe you should use 1 session per request: one request fetches the data, another request updates the data, and so on... To me, the only correct way is to use sessions with a very short lifespan and using your entities in a detached manner (= reattaching them when you need to initialize collections, update the entity itself, ...).


I've been doing NH for about 100 hours at this point. It does seem the documentation leans to short lived sessions, but it also seems to indicate that opening sessions is expensive.

For some db's like Sybase opening a connection is very expensive and also concerns licensing issues. Lot's of windows application I've worked on do have one main connection passed to all the sub things, such as the one connection per form thing.

My feeling is that it's a better oo design to encapsulate the sessions more similar to the 1 session per request scenario, if that works out from a resource standpoint.

I'm curious as to how you would have one request fetch the data and another update it. Do you use non-managed entities with the SetResultTransformer and then do your updates with another session?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 25, 2007 10:02 am 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
xasp wrote:
Well,

When re-attaching an entity, there isn't necessarily a roundtrip to the database. You can just Lock() an entity, modify it and then Flush() the session. The Lock() won't refetch the entity.

Hmm, when using databinding, the 'Lock' statement will be to late.
Suppose you have a button on a form, which saves the entity. The entity is being displayed using data-binding.
You click the button, lock the entity in a new session, and save the entity. At the time of the 'Lock' , the entity is already dirty, so, I don't think that NHibernate will perform the correct action. (Unable to test this out right now).

@Richard12345: opening ISessions is not expensive. Creating a SEssionFactory is expensive.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 25, 2007 10:09 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
You are correct, the Lock() will most likely throw an exception because the object is dirty (or the Flush() won't work because nothing changed to the object since the Lock().

But I'm not using databinding, so I'm not having that problem : I manually update my object between the Lock() and Flush().

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 26, 2007 2:19 pm 
Newbie

Joined: Mon Jun 25, 2007 3:59 pm
Posts: 15
@pelton: Can I take a look for your applicaton.

I'm just started to create C# WinForms application using NH .
Maybe I can imporove your code.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 27, 2007 3:50 am 
Beginner
Beginner

Joined: Sat Jul 21, 2007 3:56 pm
Posts: 27
I'm glad to see I'm not the only one trying to combine NHibernate and WinForms, especially for the session management part.

Me too, I have started creating some kind of architecture - framework, mainly as a POC. If it proves to be useful I will try to convince the developers at work to use it.

Before I started, I put forward the following requirements:
- Domain driven (usage of business entities for wrapping data and business logic)
- Database independent
- Scalability: no "long" connections towards the database
- Local unit-of-work per use case
- Unit-of-work should only commit the modifications to the data at the end of the use case
- UI-Binding logic should be as independent as possible of the business logic

(mainly for reasons compatibility with our legacy VB6 ORM and so keep the learning curve for our developers low)

Translated to NHibernate language, this means that I have a long-lived session that will typically be created by one WinForm (or a controller) but can be passed to any sub-usercontrol necessary. In the end, it should be the creatot that has the responsability to either commit or rollback the whole session.

I use a subset of the CSLA framework to handle the GUI binding.

The code is available here:

http://www.paarden.be/nhibernate/Sol_Pa ... urator.zip

I would be glad to hear your opinion!

One thing that I should take care of is the defering of the session.Save() and session.Remove() methods. Maybe by implementing some custom unit-of-work on top of the hibernate session.

Another thing is to add a service-layer to abstract the GUI part of the NHibernate code.

Tolomaüs.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 34 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.