Ok so I have an n tiered model. (WPF, Asp.Net, etc) to backend services via WCF. These services use NHibernate to communicate with the database. Some of these services will be run in InstanceContextMode.Single mode.
Questions:
In singleton service instances should I try to utilize 1 session object for the entire time the wcf service is alive to get the most out of my cache?
If I use 1 session instance in this singleton instance and never create new ones I assume I have to worry about eventually removing cached entities from the session or dumping it all together to avoid performance issues with the session?
Is it a good idea at all to use the session in this way for a singleton wcf service? It seems like it would be if I want to utilize caching.
Should I utilize 2nd level cache in a scenario like this?
Outside of this scenario when should I avoid caching? I would assume that I would want to avoid it in any sort of batching scenario where a large number of objects are created/updated and never really used again outside of the creation or updates.
Are items automatically cached in session when I create/read/update/delete or do I need to specify something in the mapping files or configuration?
1-3: As far as I know, ISession objects are supposed to be light-weight, short-lived objects, which live only for the duration for which they're needed. I would advise AGAINST using the same ISession object for the whole lifetime of your service.
What I would suggest instead is using the same ISeessionFactory instance, and creating new ISessions from it as necessary (you can try something similar to Session-Per-Request pattern).
If you enable 2nd level cache, you can have all the benefits of caching in this scenario.
5 Yep, pretty much. Also remember that 2nd level cache instance is per ISessionFactory instance. that means that if you're using more than 1 ISessionFactory instance you'll have a lot of problems with your cache.
6 for 1st level cache you don't need to define anything.
for 2nd level cache you need to enable the cache when you configure nHibernate (fluently, in my case):
.Cache(c => c.UseQueryCache()
.ProviderClass(
isWeb ? typeof(NHibernate.Caches.SysCache2.SysCacheProvider).AssemblyQualifiedName //in web environment- use sysCache2
: typeof(NHibernate.Cache.HashtableCacheProvider).AssemblyQualifiedName //in dev environmet- use stupid cache
))
)
and specify for each entity and each collection that you want to enable cache for them:
mapping.Cache.ReadWrite().Region("myRegion");
and for a collection:
mapping.HasMany(x => x.Something)
.Cache.ReadWrite().Region("myRegion");
Related
Can Redis be used as a self populating cache (or pull-through cache) ?
In other words, is it able to create an entry on the fly if this entry is not cached yet ?
Redis is just a store: you add things to it and retrieve them back again. It has no awareness of what you are using it for (caching) or knowledge of the backend it would perform lookups from, that will depend on the application handling the request and using Redis to cache.
Can Redis be used as a self-populating cache (or pull-through cache)?
Yes! But Redis doesn't have an implementation for self-population.
So you just have to implement it yourself and it's easy too.
Define a wrapper class that extends(is-a relation) a redis client(of your choice).
Define Factory interfaces to create objects.
Override necessary methods that require pull-through implementation
3.1 If the key already exists, return it.
3.2 Otherwise use factory interfaces to create the value, cache it and return it.
Hope this answer is generic enough for any redis client.
I have some legacy code that used to open its own Sqlconnection. And I would now like to use the SqlConnection Nhibernate creates.
But I'd rather avoid to change the code a lot (DI, adding loads of settings, ...), so, Is there a simple (convienent) way to get the current Nhibernate session?
No. What is current NHibernate session anyway?
In a web application, each http request must work with its specific NHibernate session(s).
In a desktop application, each screen will probably use one session for each of their actions.
The NHibernate session is not supposed to be used as a singleton.
You should probably use your session factory to open a new NHibernate session in your legacy code then use its CreateSQLQuery method. Your session factory should usually have a singleton lifetime.
If you bound your NHibernate sessions to some context meaningful for your application (such as the HttpContext, CallContext), you may instead get it from there. Beware of cases which may cause contexts losses (async/await configured for not restoring context, asp.net thread agility (do not cause HttpContext losses but CallContext losses), ...).
I wonder what is the best way to manage NHibernate Session Context
when using NH data layer from Xsockets controller.
Particularly I refer to self hosted winservice/console application or Azure worker role,
where HTTPContext is not available.
Of course there is always an option to create and dispose session per call, but that means a performance hit, so better reuse sessions in some way.
My controller provides API for CRUD operations in underlying NH repository and is pushing updates to relevant subscribers when certain records are updated in DB.
Your ideas appreciated :)
I'm using StructureMap to handle dependencies and create a NestedContainer to handle session per request. Don't have to mess with CurrentSessionContext or HttpContext anymore for storing session.
http://structuremap.github.io/the-container/nested-containers/
You could even just create a middleware UnitOfWork if you are using OWIN with WebAPI.
Since XSockets has state is will be bad for your database if you open the connection in the OnOpen event since the connection will remain open as long as the socket is open. Best is to use the repository only in the methods calling the CRUD operations as briefly as possible.
To get the instance of your repository should not be a bottleneck in this case.
I will be happy to review any code you might have.
Regards
Uffe
I am building a web application, and whenever I make a database call I need a session.
I understand creating a session object is very expensive.
I am following the repository pattern here: http://web.archive.org/web/20110503184234/http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx
He uses something called a UnitOfWork to get the session.
For a web application, shouldn't I be storing the Session in Request.Items collection? So its only created once per request?
Do I really need UofW?
The session IS the unit of work - its basically used to store changes until you flush them to the db. Save a static session factory at startup, and use that to create one session per web request - Request.Items seems a valid place to put the session.
The repository pattern is a wrapper over the unit of work. The repository pattern differs from the UoW pattern in that repo.Save(obj) should save the obj to the db straight away, while the UoW waits for a flush.
My advice would be to skip the repository pattern and use the ISession directly (see http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx)
In the case of NHibernate the key class is the SessionFactory, which SessionProvider is taking care of for you (if you implement it like that). Keep the SessionFactory alive, and it handles the sessions for you.
I've also seem people save the SessionFactory in their IoC.
Use this to manage your sessions:
HybridSessionBuilder
It manages and gives you access to a single session that's used across the entire application.
I know that the session is used for the database in Hibernate, but what is the task of the session in database?
Does anyone know about this?
Update:
Apologies, my links are to Java APIs (must have missed the nhibernate tag). Regardless, there will be more than one type of session for .NET also.
There will typically be more than one type of session:
The HttpSession is a server-side object:
Provides a way to identify a user
across more than one page request or
visit to a Web site and to store
information about that user.
The hibernate Session is also a server-side object:
The lifecycle of a Session is bounded
by the beginning and end of a logical
transaction. (Long transactions might
span several database transactions.)
The main function of the Session is to
offer create, read and delete
operations for instances of mapped
entity classes.
The session is server side, if by server side you mean as in the web application or client/server application sense.
It is an implementation of the Unit of Work pattern, and does stuff like keeping track of which entities that have been changed, caching of entities and making sure that a specific entity is represented by only one actual instance in the scope of the session.
The NHibernate docs describe ISession like this:
A single-threaded, short-lived object
representing a conversation between
the application and the persistent
store. Wraps an ADO.NET connection.
Factory for ITransaction. Holds a
mandatory (first-level) cache of
persistent objects, used when
navigating the object graph or looking
up objects by identifier.