How to manage NHibernate sessions in a long lived Windows forms application? - nhibernate

We are using NHibernate to manage our persistence in a complex modular windows forms application - but one thought keeps bothering me. We currently open a session on launch and open all objects through that session. I am worried that all loaded objects get loaded into the NHibernate session cache, so that they cant be garbage collected, and ultimately we will end up with the whole database in memory.
This never happens with web applications because web page requests (and even better Ajax requests) represent the perfect short lived transaction so a session can be opened and closed to handle each request.
However if I load an tree of objects in my forms application and put then into a navigation pane on the screen they may stay their for the life of the application - and at any point the user may click on them, resulting in our code needing to navigate the object relationships to other objects (which only works within an NHibernate session).
What do StackOverflow readers do to keep the benefits of NHibernate without the issues I describe?

Ayende and company usually recommend using a session per "conversation". This usually makes the session lifetime last for very short operations, so it behaves more like a web app.
For your tree case, you can use Bruno's solution #2 just fine. The objects can be lazily mapped. Then, every time you need to access a child collection, you start a conversation and reconnect the parent via ISession.Lock. Then when the databinding is done, close that session. Not too much overhead to maintain, just a few lines of code in any form that needs to carry a conversation; you can extend Form and the controls you're using to do this automatically if you're feeling sassy.
The tricky part, then, is concurrent edits from different sessions. Let's not go there!

I open a session when I need one, and I'll close it when I know that I won't need it anymore.
More specifically, for instance, if I have a form which lets me edit Customer information for instance, I'll open a session when the form gets instantiated, and I'll close the Session when the form is closed.
When I have 2 instances of that form open, I also have 2 session open.

I can see a couple of alternatives:
Eager-load the object tree (which, from what I can gather from the documentation is the default)
Detach the objects, intercept the "click" event, and load the data from the database then, with a new session. This one forces you to take care of collections by yourself, instead of relying on nhibernate, which may fall outside of the scope of the question (which asks for the benefits of NHibernate, one of which is collection management)

You can take a look to my posts on how to use uNHAddins to work with session per conversation in a Windows Forms application (uNHAddins is a project with some additionsns to NHibernate led by Fabio Maulo, current NH Lead)
The first post is this
http://gustavoringel.blogspot.com/2009/02/unhaddins-persistence-conversation-part.html
From there you have links to uNHAddins trunk.

Related

WebKitGTK about webkit_web_view_load_uri

I have a question about WebktGTK.
These days I am making a program which is can analysis web page if has suspicious web content.
When "load-failed" "load-changed" signal is emitted with WEBKIT_LOAD_FINISHED,
The program anlaysis the next page continuously by calling webkit_web_view_load_uri again again.
(http://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebView.html#webkit-web-view-load-uri)
The question want to ask you is memory problem.
The more the program analsysis the webpages, The more WebKitWebProcess is bigger.
webkit_back_forward_list_get_length() return value also increased by analysising web pages. Where shoud I free memory?
Do you know how Can I solve this problem or Could give me any advice where Can I get advice?
Thank you very much :-) Have a nice day ^^
In theory, what you're doing is perfectly fine, and you shouldn't need to change your code at all. In practice, WebKit has a lot of memory leaks, and programatically loading many new URIs in the same web view is eventually going to be problematic, as you've found.
My recommendation is to periodically, every so many page loads, create a new web view that uses a separate web process, and destroy the original web view. (That will also reset the back/forward list to stop it from growing, though I suspect the memory lost to the back/forward list is probably not significant compared to memory leaks when rendering the page.) I filed Bug 151203 - [GTK] Start a new web process when calling webkit_web_view_load functions? to consider having this happen automatically; your issue indicates we may need to bump the priority on that. In the meantime, you'll have to do it manually:
Before doing anything else in your application, set the process model to WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES using webkit_web_context_set_process_model(). (If you are not creating your own web contexts, you'll need to use the default web context webkit_web_context_get_default().)
Periodically destroy your web view with gtk_widget_destroy(), then create a new one using webkit_web_view_new() et. al. and attach it somewhere in your widget hierarchy. (Be sure NOT to use webkit_web_view_new_with_related_view() as that's how you get two web views to use the same web process.)
If you have trouble getting that solution to work, an extreme alternative would be to periodically send SIGTERM to your web process to get a new one. Connect to WebKitWebView::web-process-crashed, and call webkit_web_view_load_uri() from there. That will result in the same web view using a new web process.

WinRT Storing Session State Between Page Navigation

I am new to WinRT and was playing around with session state. I am navigating to a page to collect data and then want to return to the main page. Just before navigation I am using:
SuspensionManager.SessionState["CurrentState"] = someObject;
The object contains lists of other mildly complex objects, etc... All seems to be working but is this the correct way to use the Suspension Manager?
I have looked at other posts on the topic and some people report that it is necessary to use [DataContract] and [DataMember] attributes to all the classes that are serialized. I omitted them and it still works, (getting the data across pages). So what is the recommended approach?
I may be reading too much into one aspect your question, but the role of SuspensionManager and SessionState is to store just enough information to bring your application back to the place the user left it if the application is actually terminated while it's suspended.
In the Windows 8 application lifecycle, your app gets 'suspended' if another app comes to the foreground. While your app is suspended all of its state is retained in memory, and if reactivated (you flip back to it) everything* is restored "for free".
A suspended app could, however, also be terminated by the OS (b/c of memory pressure, for instance) and there is no opportunity to react to that scenario in your app, so what you are really doing with SessionState is storing what's necessary to 'recreate' the last place the user was at IF the application had actually terminated. It's essentially an insurance policy: if the application is merely suspended, SessionState isn't really needed.
The 'what's necessary' is the grey area, I could store all of the information about say a user profile that was in progress OR I could save just the userid that indexes into my persistent storage of all the user profile data. I generally have more of a minimalist view and will retain as little as possible in SessionState - I make the analogy that I don't need to remember everything, I only need to remember how/where to get/find everything.
There's an implication as well in your question that you're using SessionState to pass information between pages in your app, and that's not really the intent. Each page of your app is typically connected with a view model, and when you interact with a page of that app, you'd update the view model and drive additional screens and experiences from the changes already in the view model. Leaving one screen of your app and returning the main one would also imply to me that you've persisted what ever information you collected - certainly to the view model, but also to something persistent like a data base or local storage. When you revisit that page, you'd then pull the data back out of your view model (or that persistent storage); the main page doesn't need that information so why hold on to it?
Lastly, since you mentioned being new to WinRT, you may want to check out App Builder, which pulls together a number of resources in consumable chunks to lead you through building an app over a period of 30-days (though all material is available, so you can consume at any pace you want :)) The discussion of lifecycle management that's germane to your question comes in on Day 17 of that sequence.
*"everything is restored for free" doesn't necessarily mean you don't have any work to do when an app comes out of the suspended state. There may be stale data that requires refreshing, and connections or other transient or short-lived entities may need to be refreshed/recreated.

Sharing Non-Persistent Objects Between Contexts in Core Data?

I was wondering if there is a way to share an NSManagedObject between two or more NSManagedObjectContext objects running in the same thread.
I have the following problem: I have one main context shared through all my code in the application and several different contexts that are created for each remote fetch request that I issue. (I created a custom class that fetches remotely and inserts all the objects found in the server in his own NSManagedObjectContext). Those fetch requests may run simultaneously since they use NSURLConnection objects that may end at different times. If the same remote object gets fetched by different connections, I will end up with duplicates at the moment of saving and merging the context with the main one. (That is, objects that have the same remote ID but a different objectID).
One possible solution would be to save (and so persist) every object as soon as it is created but I can't do that because it may have some relationships that may still have not been filled and won't validate during the save operation.
I'm really looking forward to a method that allows you to share the same non-persistent instance of an object between context. If anybody has encountered this issue and came up with a solution, I would be pleased to know!
Context cannot communicate between each other save through their stores. However, you can insert a managed object with a nil managed object context and it will be independent (albeit without relationships) of any context. You could pass that independent managed object around however you wished and insert it into a context when you needed to persist it. This is dangerous but possible.
However, if you're not running each connection on a separate thread then you don't gain anything by having multiple context. Each connection object will activate its delegate in sequence on the main thread. In this case, your easiest solution would be to use the same delegate for all the connections and let the delegate handle the insertions into a single context. To prevent duplication, just do a fetch on the remoteID and see if you get back an extant object before inserting a new object for that remoteID.
I don't think what you want to do is possible. I mean if you want to share changes between different contexts, you got to use notifications and merge it whenever did save or did change occur. But in your case, I'd say just use 1 context and save in the end. Or a less elegant way: save all the remote ids temporary in your app and check before inserting new ones. In this case, you can continue use multiple contexts and save after each didfinishloading.

Implementing auto-save in WPF / MVVM / NHibernate

My client likes programs like Microsoft OneNote where changes are saved automatically, and he can choose to discard when he explicitly wants to do so. I will have to implement some undo functionality, but I'll figure that out some other time.
With NHibernate, I suppose I can call ISession.Update on every single property / binding change, but I can see real pain with this approach down the road. I am not a fan of timers, but maybe a 5 second timer that starts on property / binding change and at timer end use BackgroundWorker thread to save to db.
What do you think?
A ISession.Update on every property-change isn't a good idea normally. The property-change-events are fired quite often. It could slow down your application when you do ISession.Update on every change. This will probably lead to a bad user experience.
In our Application has the same behavior. We store the changes when a View is closed (an some other related event). For example when the user closes a tab, the data which was displayed in that tab is closed.
An additional timer is probably a good idea to prevent data loss when the application crashes / unexpected happens.

Load vs Get in Nhibernate

The master page in my web application does authentication and loads up the user entity using a Get.
After this whenever the user object is needed by the usercontrols or any other class I do a Load.
Normally nhibernate is supposed to load the object from cache or return the persistent loaded object whenever Load of called. But this is not the behavior shown by my web application. NHprof always shows the sql whenever Load is called. How do I verify the correct behavior of Load?
I use the S#arp architecture framework.
Actually, calling Load on an entity not marked as lazy causes immediate loading. That is because non-lazy entities are never proxied. In this case, it just acts the same way as Get.
If you use Get, then a hit to a database is made.
If you use Load, no hit to a database is made, but the object (User in your case) is created with 'lazy loading'. So when you check a property it knows that you want data so it hits the database with a query to get the data.
If you want to get an object from cache, you need to consider 2 options.
First level cache, is a cache that is in use in ONE session. So when you close a session or load the same object in a different session, you get additional hits.
Second level cache works accross all sessions. If one session gets the object, the other session gets it from cache.
So what you want is probably a second level cache.