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..).
Related
I am building an MVC 3 Application and have a question about one example scenario.
I have two entities - Order and OrderDetails.
Order data is filled on one page, detail is added, edited, deleted on other three pages.
Once order and details are filled I save this bunch of data to database.
As you can see, during user work and before data is saved to the DB, I need to store the order and details data into some kind of in-memory or similar object.
Now, if I store this object in Session then I am breaking scalability - application cannot be spanned across multiple machines.
Is there a Pattern or Approach which allows scalability and do scenarios like described?
Note: Solution other than Sql-Server Session State
have a look at the State Server Session
StateServer mode, which stores session state in a separate process called the ASP.NET state service. This ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
http://msdn.microsoft.com/en-us/library/ms178586.aspx
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.
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.
With linq, do you create a single dbContext per request like nHibernate requires (for performance reasons, creating sessions in nhibernate from what I understand are an expensive call).
i.e. in my asp.net-mvc application, I may for a given action, hit the database 5-10 times on seperate calls. Do I need to create a context and re-use it for the entire request?
DataContexts are intended to be used for a single set of actions interacting with your database. I know, that's vague. Their usage is situational. If you are doing related, or specifically sequential activities, then one DataContext is probably good for you. If you are doing unrelated or parallel activities, consider using a DataContext for each activity.
Consider a few guidelines:
Entities retrieved by one DataContext can only be used (read: updated, deleted, etc.) by that same DataContext. If you need to match up objects across separate DataContexts, you'll have to do something such as running a LINQ query to select objects with the same primary key.
LINQ to SQL uses optimistic concurrency.
Dispose of the DataContext when you are done with it (letting it go out of scope and be garbage collected is fine)
Do not use a static or shared DataContext.
When I did a small app using LinqToSql, I found the app was very sluggish when i did a create-use-dispose of a DatabaseContext object each time I had to hit the database.
When I moved to sharing the DBContext across multiple requests... the app suddenly came back to life w.r.t. responsiveness.
Here's a question that I posted which is relevant
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.