Recently I've been integrating NHibernate into our server application that exposes multiple services. The core service manages multiple instances of a class, and I understood that it is recommended to use the session-per-request pattern. So far so good.
One of the other services is a Site Settings service, which effectively manages a singleton: there is only a single instance of SiteSettings. I can follow the session-per-request pattern with this service as well, but it seems odd. Do I really need to create a new session for each request here? Why not create a single session for the service and keep using it? One of the advantages of the session-per-request pattern is that the session does not eventually cache all objects in the model. However, since I will only ever load a single instance in the session, I think this should not be a concern. Would I be better off using IStatelessSession rather than ISession?
Are there other reasons to use session-per-request here? One concern that comes to mind is what happens in case of a disconnection to the DB. Can I keep using the same session even after a DB error?
As an aside, I was thinking of storing each setting in its own column, which means I have to update the schema as settings are changed. I found this post: NHibernate Web Application - Managing User Preferences, where one of the comments is against using a table to store such configuration settings. I'm having a hard time coming up with alternatives (short of serializing the whole class and storing it as a blob). Are there different approaches?
Sessions aren't thread safe so I think you'd want more than one for your singleton
Can I keep using the same session even after a DB error?
No, presumably that would throw an exception and you're not supposed to reuse sessions after an exception. IMHO you should stick with the session per request pattern.
Are there different approaches?
Can you use a different row per config setting? So your User object would have a child collection of UserSetting objects. Each UserSetting would just be a key value pair.
Related
I have recently started working on a project using NHibernate as a ORM tool.I read about the contextual session in nHibernate and understood the idea behind it. I have a doubt in one area,
Let's say, i have a employee domain and in a http call,i am calling my repository for getting employee id =1 , 3 times.
Employee employee = _employeeRepository.GetEmployee(1);
Case 1: It will be a 1 db call
Case 2: It will be 3 db calls.
please guide me on this.
rgds
Sandy
It depends on your setup.
The first level cache will hit the DB once against each Session object you use to query with. If there is a single Session shared with this repository.. only one DB call will be made. However, if each call to the repository causes more than one Session to be created, you'll get multiple calls. This is the default.
If the second level cache is enabled, then each Session created via a SessionFactory will share the above properties. Meaning, if you have multiple repositories with multiple Session's that came from the same SessionFactory instance.. then loading the same employee from both repositories will cause a single DB call.
There is some good information in this post - it is related to Hibernate, but the basic principles still apply to NHibernate.
I would recommend you enable a second level cache (we use SysCache2) in a web environment.. so that you can guarantee that the Session's always share cached objects within a single request (assuming of course, that your Session lifetime management is per-request.. which is should be..).
I'm working with ASP.NET and I want to load once a big object (specific by user) in my controller and then use it in my view.
I though about a static property but I find some problems with it.
See : Is it a bad idea to use a large static variable?
I'm not familiar with this language and I have no idea how to properly share the same object between the different methods for each user. Could you tell me how to do that ? Do you know if singleton could be a solution ?
A singleton won't help you here if this big object is going to be different for every user.
Without knowing all the details, I'd say perhaps your best option is to store it in the Session object,
HttpContext.Current.Session["bigObject"] = bigObject;
Depending on the size & traffic, this can have performance problems, so I'd suggest you read up on the pros and cons of using Session
If you want to get to use something for the next simultaneous request, then use TempData - which is a bucket where you can hold data that is only needed for the following request. That is, anything you put into TempData is discarded after the next request completes.
If you want to persist the information specific to user, then go for Session. With session, you will have timeout, so that after certain amount of time the data stored in session will be lost. You can configure this value to much more bigger value. Apart from that when you go for Webfarm of servers, then maintaining session will be a problem, probably you might need to go for managing session in SQL Server or in some other store.
Alternatively you can Use Runtime Cache object in ASP.Net MVC to keep all the common data. Cached data can be accessed fast and we have other benefits like expiring cache etc. You can share this Cache object across users, or you can maintain different cache objects for different users, that is purely dependent on your logic. In case of webfarms, yo u have distributed cache servers like redis, Azure Cache service etc., which you can use them.
I've got an mvc project. we have some data that must collected for each user. i created some singleton class to cache data for better responsibility.
somebodies avoided using singleton class in their projects.
i want to know do you prefer this and if not, what's your replacement??
The proper way in 99% is not reinventing the wheel. If you're not all right with System.Web.Caching.Cache, you can use System.Runtime.Caching.MemoryCache instance per user.
I don't see a reason why you should not cache data in your singleton. I'm also using this way of caching in order to greatly reduce the amount of database calls. Just make sure that you keep your cache up to date.
I don't know your project and its environment, but in my case it there were situations when the data in the DB gets changed from another application. I implemented a database trigger to resolve this issue. You should consider doing the same in your case, so whenever some of your locally cached data changes in the DB, you get notified and can update the cache.
I think I don't have to mention this, but caching of course usually only makes sense for relatively static data that does not change very often.
If I am using a SqlConnection, apparently the best practice is to dispose of it ASAP, and let the connection pooling handle the details. Should I follow the same pattern when I am using System.Data.Linq.DataContext?
Should I create my context once and pass it along to my methods, or should I get the connection string from my config file and create the contexts multiple times and save on passing the parameters?
Edit: A useful link about identity maps: Architecting LINQ To SQL Applications, part 7
You should keep a data context around only as long as necessary to perform an operation.
The reason for this is that it uses something called an Identity Map so that every time you select say customer 1 you get the same object back. This means it is holding lots of references and will consume more and more memory over time and these results will become increasingly stale.
In the case of a web app it is common to create one per request and the DataContext class is optimised for quick creation.
I'm new to NHibernate (my 1st big project with it).
I had been using a simple method of data access by creating the ISession object within a using block to do my grab my Object or list of Objects, and in that way the session was destroyed after exiting the code block.
This doesn't work in a situation where lazy-loading is required, however.
For example, if I have a Customer object that has a property which is a collection of Orders, then when the lazy-load is attempted, I get a Hibernate exception.
Anyone using a different method?
Session management:
http://code.google.com/p/dot-net-reference-app/source/browse/trunk/src/Infrastructure/Impl/HybridSessionBuilder.cs
Session per request:
http://code.google.com/p/dot-net-reference-app/source/browse/trunk/src/Infrastructure/Impl/NHibernateSessionModule.cs
check out the SummerOfNHibernate webcasts for a great tutorial... What you're looking for specifically doesn't come until webisode 5 or 6.
Keep your session open for your entire unit of work. If your session is life is too small, you cannot benefit from the session level cache (which is significant). Any time you can prevent a roundtrip to the database is going to save a lot of time. You also cannot take advantage of lazy loading, which is crucial to understand.
If your session lifetime is too big, you can run into other issues.
If this is a web app, you'll probably do fine with the session-per-httpRequest pattern. Basically this is an HttpModule that opens the session at the beginning of the request and flushes/closes at the end. Be sure to store the session in HttpContext.Items NOT A STATIC VARIABLE. <--- leads to all kinds of problems that you don't want to deal with.
You might also look at RhinoCommons for a unit of work implementation.
Since you are developing a Web App (presumably with ASP.NET), check out NHibernate Best Practices with ASP.NET at CodeProject.