Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate session management?

Firstly, let me give a brief description of the scenario. I'm writing a simple game where pretty much all of the work is done on the server side with a thin client for players to access it. A player logs in or creates an account and can then interact with the game by moving around a grid. When they enter a cell, they should be informed of other players in that cell and similarly, other players in that cell will be informed of that player entering it. There are lots of other interactions and actions that can take place but it's not worth going in to detail on them as it's just more of the same. When a player logs out then back in or if the server goes down and comes back up, all of the game state should persist, although if the server crashes, it doesn't matter if I lose 10 minutes or so of changes.

I've decided to use NHibernate and a SQLite database, so I've been reading up a lot on NHibernate, following tutorials and writing some sample applications, and am thoroughly confused as to how I should go about this!

The question I have is: what's the best way to manage my sessions? Just from the small amount that I do understand, all these possibilities jump out at me:

  • Have a single session that's always opened that all clients use
  • Have a single session for each client that connects and periodically flush it
  • Open a session every time I have to use any of the persisted entities and close it as soon as the update, insert, delete or query is complete
  • Have a session for each client, but keep it disconnected and only reconnect it when I need to use it
  • Same as above, but keep it connected and only disconnect it after a certain period of inactivity
  • Keep the entities detached and only attach them every 10 minutes, say, to commit the changes

What kind of strategy should I use to get decent performance given that there could be many updates, inserts, deletes and queries per second from possibly hundreds of clients all at once, and they all have to be consistent with each other?

Another smaller question: how should I use transactions in an efficient manner? Is it fine for every single change to be in its own transaction, or is that going to perform badly when I have hundreds of clients all trying to alter cells in the grid? Should I try to figure out how to bulk together similar updates and place them within a single transaction, or is that going to be too complicated? Do I even need transactions for most of it?

like image 892
IRBMe Avatar asked Jul 19 '09 16:07

IRBMe


People also ask

What is NHibernate session?

The NHibernate session encapsulates a unit of work as specified by the unit of work pattern.

Is NHibernate thread safe?

The NHibernate ISession is not thread-safe, that is, it shouldn't be shared by multiple threads. The ISessionFactory, however, is thread-safe, and thus it should be used to create ISession instances as needed.

What is dialect in NHibernate?

dialect. This property is required. A class to build RDBMS-specific SQL strings. Typically, this is one of the many dialects from the NHibernate. Dialect namespace.


2 Answers

I would use a session per request to the server, and one transaction per session. I wouldn't optimize for performance before the app is mature.

Answer to your solutions:

  • Have a single session that's always opened that all clients use: You will have performance issues here because the session is not thread safe and you will have to lock all calls to the session.
  • Have a single session for each client that connects and periodically flush it: You will have performance issues here because all data used by the client will be cached. You will also see problems with stale data from the cache.
  • Open a session every time I have to use any of the persisted entities and close it as soon as the update, insert, delete or query is complete: You won't have any performance problems here. A disadvantage are possible concurrency or corrupt data problems because related sql statements are not executed in the same transaction.
  • Have a session for each client, but keep it disconnected and only reconnect it when I need to use it: NHibernate already has build-in connection management and that is already very optimized.
  • Same as above, but keep it connected and only disconnect it after a certain period of inactivity: Will cause problems because the amount of sql connections is limited and will also limit the amount of users of your application.
  • Keep the entities detached and only attach them every 10 minutes, say, to commit the changes: Will cause problems because of stale data in the detached entities. You will have to track changes yourself, which makes you end up with a piece of code that looks like the session itself.

It would be useless to go into more detail now, because I would just repeat the manuals/tutorials/book. When you use a session per request, you probably won't have problems in 99% of the application you describe (and maybe not at all). Session is a lightweight not threadsafe class, that to live a very short. When you want to know exactly how the session/connection/caching/transaction management works, I recommend to read a manual first, and than ask some more detailed questions about the unclear subjects.

like image 60
Paco Avatar answered Sep 27 '22 23:09

Paco


Read the 'ISessionFactory' on this page of NHibernate documentation. ISessions are meant to be single-threaded (i.e., not thread-safe) which probably means that you shouldn't be sharing it across users. ISessionFactory should be created once by your application and ISessions should be created for each unit of work. Remember that creating an ISessions does not necessarily result in opening a database connection. That depends on how your SessionFactory's connection pooling strategy is configured.

You may also want to look at Hibernate's Documentation on Session and Transaction.

like image 35
0sumgain Avatar answered Sep 28 '22 00:09

0sumgain