The 'Permanent' SessionFactory, ASP.NET MVC and nHibernate - asp.net-mvc

I've been building an application with Fluent nHibernate/ASP.NET MVC - and I've dug around and figured out that it's considered most appropriate practice to keep a 'permanent' SessionFactory open, and then use sessions for each request to the database. Okay, this sounds good...
I'm quite confused on how to accomplish this, though. Everything I find assumes an entire structured framework that uses some kind of IoC container system ...and that's just too advanced for what I have so far. Are there any more simple examples of how to implement this kind of design?
I've taken a look at Where can I find a good NHibernate and ASP.NET MVC Reference Application
And even read the book "ASP.NET MVC in Action", but it's example is just far more complicated than what I am trying to achieve. I thought a singleton model would work in the Application_Start of the 'global.asax' but that didn't yield the results I had hoped for. It would keep disposing of my factory and never recreating it.

You could expose the ISessionFactory as singleton:
public sealed class FactoryManager
{
private static readonly ISessionFactory _instance = CreateSessionFactory();
static FactoryManager()
{ }
public static ISessionFactory Instance
{
get { return _instance; }
}
private static ISessionFactory CreateSessionFactory()
{
// TODO: configure fluentnhibernate and create a session factory
}
}
Now you could use FactoryManager.Instance in your code:
using (var session = FactoryManager.Instance.OpenSession())
using (var tx = session.BeginTransaction())
{
// TODO: use the session here
tx.Commit();
}

Make a static GetSessionFactory method on your global MvcApplication class. This method initializes a session factory the first time it is called and stores it as a private static variable. Upon subsequent calls, it simply returns the static variable.
This method can also check to see if the object is null or disposed and recreate as necessary, though it shouldn't happen since the variable would be static and thus, stay alive for the duration of the application's lifetime.

Related

Dispose DbContext in MVC Controller, which way "better"?

In MVC 5, the scaffolding codes will have something like:
public class MyController : Controller
{
private MyContext db = new MyContext();
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
otherwise, I need to have
using (var db = new MyContext())
{...}
in each action.
The codes look good, so I don't need to use using in each action. However, is this subject to preference of programmers, or such style has some advantage over using in each action that needs to use the dbcontext?
Both solution are good - both solution will dispose db context. But in my opinion the second option will be better - you create db context just where you have to.
But what if another class (some service class) also uses db context. It is good practice to have one db context for the whole web request. In that case you should pass previous created db context to all classes that use db context to prevent creating new db context in all clases. So I will consider usage of IoC containers. IoC container will resolve your dependencies and also will mange object lifetime. Bellow
I listed a few IoC containers:
Castle Windsor
Spring Framework
StructureMap
For simple scenarios calling Dispose (or using Using) is not necessary at all :)
"The default behavior of DbContext is that the underlying connection is automatically opened any time is needed and closed when it is no longer needed."
From here:
http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext/
In terms of best practices, you should absolutely use the template scaffolded stuff and not mess with the using(){} pattern unless you have some really good overriding reason. Both solutions produce the same result, but both are not good solutions. The reason why the template has a single DbContext is to make it easier to test - heres an example:
public class SomeController : Controller
{
private ApplicationDbContext db;
public AccountController()
{
db = new ApplicationDbContext();
}
public AccountController(ApplicationDbContext context)
{
db = context;
}
}
The first constructor with no arguments is that which is used in production and automatically creates a new db context based on the app config file. The second allows you to inject a mocked db context when you are doing unit testing.
At the end of the day, this question and my answer isn't really about disposing db contexts - it's about why the code template designers chose to take the approach they did and why it will help you. You should read more on unit testing.
A Using statement calls the Dispose() method at the end of the Using block automatically. The Using statement calls the Dispose() method even if there was an error in the code.

When/How to dispose DbContext when returning IQueryable?

I've recently started using IQueryable inspired by http://www.codethinked.com/keep-your-iqueryable-in-check. So I've been used to doing this in my repos:
public IEnumerable<POCO> GetById(int id)
{
using (var ctx = new DbContext())
{
var query = from ...;
return query.ToList();
}
}
Now I'm doing this instead:
public IPageable<POCO> GetById(int id)
{
var ctx = new DbContext()
var query = from ...;
return new Pageable(query);
}
But I'm wondering if this is the best way to handle new DbContext().
Is it better to place DbContext as a class member
public class Repo
{
private DbContext _ctx = new DbContext();
}
Or even injection it
public class Repo
{
private DbContext _ctx;
public Repo(DbContext ctx)
{
_ctx = ctx;
}
}
What are the pros and cons to:
a new DbContext in each method.
a new DbContext per object (class member).
injecting DbContext.
I'm using Ninject so I can use .InRequestScope(); (if that should effect the answer)
A couple other questions:
Should my repo implement IDisposable if DbContext is kept as a class
member?
Is there an even better way to handle disposal of DbContext then the above?
I would always go with injecting the DBContext, with the InRequestScope. Gives all benefits of dependency injection.Ninject would also dispose the DBContext on the end of the cycle as DBContext implements IDisposable. See this thread
If you use DI, your other two questions become irrelevant.
Entity Framework loves caching. If you are constantly changing your application and reloading it in your browser, you'll probably notice that the first time you reload it, it takes a couple of seconds to load, but after that, pages are almost instantaneous. This is because MVC and EF are caching common queries that are repeatedly used, making your app faster to use after that initial load time.
Because of this, it is not of huge concern where you create your DBContext. Yes, creating anything takes time. However, EF will recognize these queries and will load them quickly, even if you have just created a new instance of your context.
On a side note, if your application doesn't have a large amount of queries, the use of Using blocks around your DbContext would be considered ideal (as this handles the dispose for you), but again, the runtime and memory use results would be negligible.

how to use unit of work pattern in public static

I am Use this code For select 4 Last Record Of Database in various page
public static List<Tour> GetLastTour()
{
using (var Context = new MvcHghDbContext())
{
return (Context.Tours.Take(4).OrderByDescending(x=>x.Titl e).ToList());
}
}
How To Use unit of work pattern in static Method in Static Class ?
But Static Constructor Erorr!
such this code
plz help me:
public static class DropDownList{
private readonly ICatHotellService _catHotellService;
private readonly ICatTourismService _catTourismService;
private readonly ICatTourService _catTourService;
private readonly IUnitOfWork _uow;
public DropDownList(ICatHotellService CatHotellService, IUnitOfWork ouw, ICatTourService CatTourService, ICatTourismService CatTourismService)
{
_uow=ouw;
_catHotellService = CatHotellService;
_catTourismService = CatTourismService;
_catTourService = CatTourService;`
}
}
The short answer is that this can't work. Static classes may only have static constructors, and these get called by the runtime when the app is created. Thus, this happens long before your dependency injection has been configured. On top of that, you should never ever ever have static data contexts in a web application, because these are shared by all users of your app, thus two users using the same data context will write over each others data model.
You are not using UoW at all. UoW means injecting one instance of the MvcHghDbContext to different classes of your service layer during a request call and not instantiating it directly each time such as your GetLastTour method.
Don't use static classes in your service layer. extract an interface from them and let the IoC container manage its life time.
Also you can use service locator pattern (such as calling ObjectFactory.GetInstance<>) every where even in static classes. It's an anti pattern and should be avoided as much as possible, because now the IoC Container is a dependency in your class.

Ninject dispose order with InRequestScope

Just started playing with ninject - and I can't get past this issue. Consider this setup:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IDataTransaction>().To<DataTransaction>().InRequestScope();
kernel.Bind<IdbAnalytics>().To<dbAnalytics>().InRequestScope();
kernel.Bind<IdbMembership>().To<dbMembership>().InRequestScope();
kernel.Bind<IAnalyticsWork>().To<AnalyticsWork>().InRequestScope();
kernel.Bind<IMembershipWork>().To<MembershipWork>().InRequestScope();
kernel.Bind<ILog>().To<Log>().InRequestScope();
...
}
With Log being injected into the above classes:
public class AnalyticsWork : IAnalyticsWork, IDisposable
{
private readonly IdbAnalytics _Context;
private readonly ILog _Log;
public AnalyticsWork(IdbAnalytics Context, ILog Log)
{
_Context = Context;
_Log = Log;
_Log.Write(LogEntryType.DEBUG, "Object Created");
}
...
}
This issue is the Log object gets disposed of ahead of the other objects (AnalyticsWork / MembershipWork). Is there any way to set the order that items should be disposed of? Or is this setup flawed?
I do not use NInject, but it sounds to me that you are registering the Log concrete as shared or per web request (as per the InRequestScope might indicate, again I do apologize for not using NInject so I am not sure what that does).
For all of the loggers I've used, NLog, Log4Net, MS' Logging Application Block, etc - they all require Transient registration, not Scoped, because they take the superclass that initiated them to write out in the log as the calling class.
As far as dispose order, I don't think you can control that with any IoC container because the object cannot be disposed in different orders if another class still has a reliance. I ran into the same issues when I first started with IoC Containers years ago and thought, "Yeah, I'll register everything as scoped!" Hehe, that didn't work out very well.
I would say your objects just need to be registered differently. Only scope the items you really need scoped, everything else as transients or singletons. I usually follow the pattern of:
Code everything singleton and code thread-safe.
If not thread-safe make it a transient and register it as such.
If I not using a unit-of-work pattern with my ORM, I will typically register my ORM containers as Scoped so they can track the object changes for the life of the request, and SaveChanges() latter (e.g. Entity Framework 4, or NHibernate's Session, etc).

How can I implement NHibernate session per request without a dependency on NHibernate?

I've raised this question before but am still struggling to find an example that I can get my head around (please don't just tell me to look at the S#arp Architecture project without at least some directions).
So far I have achieved near persistance ignorance in my web project. My repository classes (in my data project) take an ISession in the constructor:
public class ProductRepository : IProductRepository
{
private ISession _session;
public ProductRepository(ISession session) {
_session = session;
}
In my global.asax I expose the current session and am creating and disposing session on beginrequest and endrequest (this is where I have the dependency on NHibernate):
public static ISessionFactory SessionFactory = CreateSessionFactory();
private static ISessionFactory CreateSessionFactory() {
return new Configuration()
.Configure()
.BuildSessionFactory();
}
protected MvcApplication() {
BeginRequest += delegate {
CurrentSessionContext.Bind(SessionFactory.OpenSession());
};
EndRequest += delegate {
CurrentSessionContext.Unbind(SessionFactory).Dispose();
};
}
And finally my StructureMap registry:
public AppRegistry() {
For<ISession>().TheDefault
.Is.ConstructedBy(x => MvcApplication.SessionFactory.GetCurrentSession());
For<IProductRepository>().Use<ProductRepository>();
}
It would seem I need my own generic implementations of ISession and ISessionFactory that I can use in my web project and inject into my repositories?
So just to clarify - I am using NHibernate in my repository layer and want to use a session-per-(http)request. Therefore I am injecting an ISession into my repository constructors (using structuremap). Currently to create and dispose the sessions in each request I have had to reference NHibernate from my web project. This is the dependency I would like to remove.
Thanks,
Ben
Why don't you create an IHttpModule and perform your creation and disposing there (probably in the Begin_Request and End_Request events), but put your IHttpModule inside the project that has your NHibernate dependency. eg.
namespace MyWebApp.Repository.NHibernateImpl
{
public class NHibernateModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Context_BeginRequest);
context.EndRequest += new EventHandler(Context_EndRequest);
}
private void Context_BeginRequest(object sender, EventArgs e)
{
// Create your ISession
}
private void Context_EndRequest(object sender, EventArgs e)
{
// Close/Dispose your ISession
}
public void Dispose()
{
// Perhaps dispose of your ISessionFactory here
}
}
}
There is maybe a better way, I'm interested to know this as well, so any alternative suggestions?
In my opinion, you should embrace the ISession and work with it directly. The problem with many session-per-request implementations is that they delay committing database changes until the end of the HTTP request. If the transaction fails, all you can do at that point is direct the user to a generic error page. It's much better to manage the transaction on the page so that you can catch and handle errors more effectively. If you take this route then you need to access the ISession or a wrapper to control the transaction.
Also, at some point your application will probably need to use properties or methods exposed by ISession, especially Merge and Load.
Thanks for everyone's help so far. A bit more research led me to the NHibernate Burrow project.
From the project FAQ (http://nhforge.org/wikis/burrow/faq.aspx):
Burrow is a light weight middleware developed to support .Net applications using NHibernate (maybe also referred as NH in this article) as ORM framework. Using Asp.net with NHibernate could be a challenge because of the fact that NHibernate is a stateful environment while Asp.net is a stateless framework. Burrow can help solve this conflict by providing advanced and smart session/transaction management and other facilitates.
I had to jump through a few hoops to get it working in my project. Since the current release uses an old version of NHibernate I had to download the latest source from the trunk, open in VS, add references to latest version of NHibernate and recompile (fortunately no errors).
I tested NHibernate Burrow in a number of ways.
1) Continue injecting ISession into my repositories
To do this, I had to add references to NHibernate, NHibernate.Burrow and NHibernate.Burrow.WebUtil to my MVC project.
In web.config I had to set up Burrow (see http://nhforge.org/wikis/burrow/get-started.aspx) and then in my StructureMap registry add the following:
For<ISession>()
.TheDefault.Is
.ConstructedBy(x => new NHibernate.Burrow.BurrowFramework().GetSession());
I like this approach as it means my repositories (or controllers) are not coupled with Burrow. I don't really like the fact that I have to reference these three assemblies in my web project but at least I lose the code for managing the session - this is all handled by Burrow.
2) The second approach would be to set ISession in my repository constructors like so:
public ProductRepository() :
this(new BurrowFramework().GetSession()) { }
public ProductRepository(ISession session) {
_session = session;
}
I can still override ISession making my repositories testable. I then have a direct dependency on Burrow but perhaps this isn't such a bad thing?
On the plus side, the only assembly I need to reference from my web project is NHibernate.Burrow.WebUtils.
Interested to see which of the two people would go for and why.

Resources