Dispose DbContext in MVC Controller, which way "better"? - asp.net-mvc

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.

Related

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 refer to Entity Framework DbContext from MVC business objects?

I'm starting a new ASP.NET MVC project. In my last project, one of the biggest code smells was how I passed around the Entity Framework DbContext, stored it in HttpContext.Current, called SaveChanges() in my rendering event, and did all manner of (probably unseemly) related things.
Suppose that my unit of work always corresponds to a web request. What is the right way to create a DbContext, share that context to a business library (e.g. an assembly outside the MVC project responsible for processing some workflow activities), share result models back to my controller, and persist any changes?
I'll be honest, I don't know much about dependency injection. It sounds like it should be related, but I don't see how it would get me a shared context instance between my controller and my business processes in an external assembly.
If I only needed it from controllers, it would be easy. I'd stick to HttpContext. But now HttpContext has spilled over to my external library. Do I just define an interface that returns the current DbContext, and base an implementation of that on HttpContext?
Hope that's clear what I'm asking, as I'm a little lost.
Dependency injection definitely sounds like what you are after here. My preference is ninject so below is a bit of an example of how I do this with EF.
Install Ninject.MVC3 (available on nuget)
Go to \app_start\NinjectWebCommon.cs (added by the above package) and add the following to the RegisterServices method
kernel.Bind<MyContext>().ToSelf().InRequestScope(); //binding in the context in request scope, this will let us use it in our controllers
Inside a controller consume the context as follows
public class MyController : ....{
private readonly MyContext _context;
public MyController(MyContext context){ _context = context; }
//Do stuff with _context in your actions
}
This is a really simple example for you to try there are plenty of better ways to structure this as your application grows (such as ninject modules) but this will demonstrate how DI works.
A few things to note, Always make sure you bind the context in requestscope (or more frequently) as DBContext has a nasty habit of growing quite bit if it sticks around too long.
In terms of sharing it with your external stuff that can be injected too, eg
public class MyExternalLogic{
public MyExternalLogic(MyContext context){....}
}
public class MyController : ....{
private readonly MyContext _context;
public MyController(MyContext context, MyExternalLogic logic){ _context = context; ...}
//Do stuff with _context in your actions
}
In the above the same instance of DbContext will be used for both MyController and MyExternalLogic. Ninject will handle the creation of both objects.
There are also a bunch of other DI containers available which will give you very similar experiences. I highly recommend DI as it helps a lot with unit test-ability as well.
For some more examples of how I use Ninject to structure my MVC apps check out some of my projects on github, such as https://github.com/lukemcgregor/StaticVoid.Blog

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).

The 'Permanent' SessionFactory, ASP.NET MVC and nHibernate

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.

Why is my DataContext null in only one action?

I have a property on my BaseController called DataContext that holds my LINQ to SQL data context (or fake context for testing). When using a parameterless constructor (in other words, when a request to ASP.NET MVC is made), a new instance of my LINQ to SQL data context is assigned to the property:
public class BaseController : Controller {
public IDataContextWrapper DataContext { get; set; }
public BaseController() : this(new DataContextWrapper<MyDataContext>()) { }
public BaseController(IDataContextWrapper context) {
DataContext = context;
}
}
Also in my BaseController, I set some global ViewData items:
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
ViewData["Example"] = DataContext.Table<Example>().Count();
base.OnActionExecuting(filterContext);
}
This is working fine for almost every action. The only one that doesn't work is the Logout action on my AccountController:
public ActionResult Logout() {
FormsAuth.SignOut();
return RedirectToResult("Login");
}
This raises a NullReferenceException during BaseController.OnActionExecuting. When executing that particular action, the DataContext property is null.
Why would this only occur on one action?
Note: IDataContextWrapper and DataContextWrapper simply wraps the existing functionality of the LINQ to SQL DataContext object so that it can be replaced with a fake context in unit tests. It doesn't do any disposing on its own, but leaves it up to the underlying DataContext, so I'm pretty certain that's not the problem.
To follow up my comment, check out this link and more specifically the link Microsoft documentation here which state:
In general, a DataContext instance is designed to last for one "unit of work" however your application defines that term. A DataContext is lightweight and is not expensive to create. A typical LINQ to SQL application creates DataContext instances at method scope or as a member of short-lived classes that represent a logical set of related database operations.
Microsoft did a terrible job explaining this and frankly explaining using Linq in an n-tier environment in the first place. In my particular case, I had one (static) datacontext implemented via Singleton pattern, which I am guessing is what you have done as well. ( As it is the most logical design, IMHO ). This however, is extremely NOT the way to do things. In my case, the fix was actually pretty easy, changing my GetDataContext() call to return a new DataContext every time, instead of returning the static instance. This however, you will find, creates a whole new crop of problems. None of them are insurmountable once you figure them out, but definitely a pain.
If you have such a setup ( Singleton accessors for your DataContext), change it to see if it fixes your problem.
Regardless, do not use a global DataContext, nor persist a DataContext if dealing with an n-tier architecture.
Even if this doesn't solve your particular problem, I highly suggest you re-architect your solution to make DataContexts have a unit of work lifespan, if it hasn't bitten you already, it will.
For reasons that I don't quite understand, when a new AccountController is created for the Logout action, ASP.NET MVC is using the second constructor with a null parameter (could be a bug?). I changed the class to create a new default DataContext when the parameter is null:
public class BaseController : Controller {
public IDataContextWrapper DataContext { get; set; }
public BaseController() : this(null) { }
public BaseController(IDataContextWrapper context) {
DataContext = dataContext ?? new DataContextWrapper<MyDataContext>();
}
}
Now it works.
It strikes me as strange that ASP.NET MVC used the default constructor in some cases, and an overload in others, though. Can anyone shed some light on this?

Resources