asp.net mvc3 Code First (Database Singleton) - c#

I am working on asp.net mvc using code first. I noticed that once i create a new controller, the controller template shows dispose overridden method that just has one job; dispose db variable created at the top of this controller.
I am thinking of changing this to use singleton pattern with my DBContext class.
I tried it and it worked fine. except that i needed sometimes to access database from global.asax. (sometimes) is throws an exception.
Have anyone thought to do the same? Any ideas?
Thank you

personally I would follow a completely different approach, see my answer here: https://stackoverflow.com/a/7474357/559144 I would not use Singleton and would not hardlink MVC which is a UI framework with the DAL (EF in your case).
about not using singleton, let the database handle concurrency; it's one of the things Database servers do the best ;-)

We use EF context as a singleton per http context. I also would not hard link EF with MVC, but you can still be sure that each http context deals with a single EF context instance by using dependency injection (we use Unity).
We also access the context in global asax to do db initialization and seeding for development. Again, you can use a DI container to get an instance of the EF context.
public interface IUnitOfWork : IDisposable
{
int SaveChanges();
}
public class MyEfContext : DbContext, IUnitOfWork
{
// your custom context code
}
Using a singleton-per-http-context lifetime for the IUnitOfWork dependency injection isn't an approach to help deal with concurrency in our case. We do it because when dealing with EF entities, we need to make sure all of the selects / inserts / updates / deletes always happen with the same context instance. EF does not let you attach entities to multiple contexts, and we use singleton per http context for this reason.

Related

Singleton Scope for EF's DbContext

so I am currently working on an ASP.NET MVC web application that uses Entity Framework, I'm also using Ninject for Dependency Injection.
So basically, at the moment, this is how I register my DbContext and Services with Ninject.
kernel.Bind<DbContext>().To<MyApplicationContext>().InSingletonScope();
kernel.Bind<IAccountService>().To<AccountService>().InSingletonScope();
kernel.Bind<IRegionService>().To<RegionService>().InSingletonScope();
kernel.Bind<IRoleService>().To<RoleService>().InSingletonScope();
I register them with InSingletonScope, which means that they will only be created once and used throughout the lifetime of the application (at least how I understand it).
Controllers:
private IAccountService _accountService;
public MemberController(IAccountService accountService)
{
_accountService = accountService;
}
However, I have a deep feeling that this singleton scope will cause problem in my web application especially for the Entity Framework's context, due to it being singleton.
I am already facing a minor issue due to this, if I manually update the database using SQL Management Studio, the data in my web application's Entity Framework wouldn't update until I restart the application (seems to be some caching mechanism in EF).
--
However, if I remove the InSingletonScope, I will randomly get errors from EF saying that:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
I understand why this happens because the DbContext initialized by AccountService could be different from say, RegionService. But I have no idea how I can resolve this.
My understanding of Dependency Injection is still very limited, so can anybody please advice?
--
EDIT: I've tried changing to InRequestScope for all the injections, but I'm still getting
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
When trying to insert a new entity with related object (foreign key) from another service in my application. That means they are still using a different DbContext, what is happening?!
FINAL EDIT: Ok I've found the problem, it was my caching mechanism that was caching a previous request, causing the relationship issue on all subsequent request.
The lifetime of some services including DbContext can be configured this way:
services.AddDbContext<ApplicationDbContext>(
options => { options.UseSqlServer("YourConnectionString"); },
ServiceLifetime.Singleton);
REF
Singleton-scope is a very bad idea for your context. Request-scope is what you should be using, as it's essentially a singleton for the life of the request.
As to why you're getting errors when using request-scope, I can't say for sure. Assuming that the entities you're utilizing all originate from the same context type, and that you're properly injecting the context everywhere it's needed, there should never be multiple context instances in play.
EDIT
After re-reading your question, it sounds as if your services are actually initializing the context in their constructors or something. If that's the case, that's your problem. You context should be injected into your services, i.e.:
public class AccountService : IAccountService
{
protected readonly DbContext context;
public AccountService(DbContext context)
{
this.context = context;
}
...
}
Then, Ninject will properly inject the request-scoped instance of MyApplicationContext when newing up any of the services.
Dan, you are creating a bottleneck when you scope a single DBContext for the entire application. Underneath the hood, Entity Framework will handle how many objects you need rather efficiently. If you go deeper into internals, the actual objects contacting the database do the same thing. So your attempt to optimize by making a singleton may actually be creating a very big problem.
I've finally managed to resolve this issue by using InRequestScope instead of InSingletonScope.
Initially, I was still facing the same problem after changing to InRequestScope because of my existing caching mechanism on my services layer.
Thus, all subsequent requests were using the initially-cached entity object, that was why I was getting multiple instances error from EF.
--
If you are still facing the
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
error after changing to InRequestScope, make sure your entities are not somehow cached or stored for subsequent HTTP requests uses.

Lifetime of dbContext when using Async Controllers via dependency injection

In the past I have used AutoFac to inject a EntityFramework DB context to various services on a InstancePerRequest schedule.
builder.RegisterType<MyDataContext>()
.As<IDataContext>()
.As<IUnitOfWork>()
.InstancePerRequest();
This has allowed me to share the context across services when injecting multiple services into a controller.
// Note each of these services take a IDataContext via constructor injection
public FilesController(
IAnalysisService analysisService,
IUserService userService)
{
}
I have an action filter that commits my Context at the end of each action request (I am probably looking at changing this but for now it suites my purpose of this question).
public class UnitOfWorkActionAttribute : ActionFilterAttribute
{
public IUnitOfWork UnitOfWork { get; set; }
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
UnitOfWork.SaveChangesAsync().WaitAndUnwrapException();
}
}
My reading of async in MVC is that the thread that started the request is not guaranteed to finish it due to it being freed up when using await.
In AutoFac injection does this mean that the UnitOfWork instance injected into the ActionFilterAttribute might differ from the one injected into the Controller or is InstancePerRequest not effected by changes to the Thread handling the request?
InstancePerRequest won't be affected by changes to the Thread handling the request, as it does not store anything inside of the Thread. If you read the source of the InstancePerRequest() method you'll see that it's just calling InstancePerMatchingLifetimeScope with a well-known scope tag.
On the other side of things, in the AutoFac.Mvc project, you'll see that in the RequestLifetimeScopeProvider class that it stores the scope in the HttpContext, which is immune to changes in the executing thread.
The only remaining question is: Does your filter execute inside of the scope of the AutoFac filter that starts the request scope? Well, the surest way to find out is to make sure that your UnitOfWork gets injected into your filter. Assuming it does, you can be assured that it is the SAME UnitOfWork that existed throughout the rest of the request.
I would agree with others' suggestions to NOT commit your UnitOfWork (DbContext) in a filter like this. One set of reasons you've already read in the this answer. Another reason is that it implies (to me) that your chosen pattern is to NEVER call SaveChanges() from inside of your individual service methods and instead wait until the end to atomically commit everything. This will work fine until the moment where it doesn't, for example when EF updates or inserts your entities in the wrong order. At this point, you'll have painted yourself into a corner.
I might also presume that you're doing this as a way of avoiding the headaches of explicitly using Transactions, since if you only call SaveChanges() once, all updates will happen in a single, isolated transaction internal to SaveChanges() and you can therefore avoid this pain. This idea of never using explicit transactions in EF, too, is a trap once your app grows to any substantial complexity, though "popularly" championed in various articles around the net. I suggest you plan your infrastructure to accommodate it. Thankfully if you're using something like AutoFac, you can fairly transparently either attach a transaction to your request scope (the all-or-nothing approach) or create a new scope at runtime that contains your transaction, for when you selectively want a transaction.
One possible solution is to call your read-only service calls without a surrounding transaction (to avoid any DB locking) and only use transactions when you know you'll be writing to the database.

One DbContext per web request... why?

I have been reading a lot of articles explaining how to set up Entity Framework's DbContext so that only one is created and used per HTTP web request using various DI frameworks.
Why is this a good idea in the first place? What advantages do you gain by using this approach? Are there certain situations where this would be a good idea? Are there things that you can do using this technique that you can't do when instantiating DbContexts per repository method call?
NOTE: This answer talks about the Entity Framework's DbContext, but
it is applicable to any sort of Unit of Work implementation, such as
LINQ to SQL's DataContext, and NHibernate's ISession.
Let start by echoing Ian: Having a single DbContext for the whole application is a Bad Idea. The only situation where this makes sense is when you have a single-threaded application and a database that is solely used by that single application instance. The DbContext is not thread-safe and since the DbContext caches data, it gets stale pretty soon. This will get you in all sorts of trouble when multiple users/applications work on that database simultaneously (which is very common of course). But I expect you already know that and just want to know why not to just inject a new instance (i.e. with a transient lifestyle) of the DbContext into anyone who needs it. (for more information about why a single DbContext -or even on context per thread- is bad, read this answer).
Let me start by saying that registering a DbContext as transient could work, but typically you want to have a single instance of such a unit of work within a certain scope. In a web application, it can be practical to define such a scope on the boundaries of a web request; thus a Per Web Request lifestyle. This allows you to let a whole set of objects operate within the same context. In other words, they operate within the same business transaction.
If you have no goal of having a set of operations operate inside the same context, in that case the transient lifestyle is fine, but there are a few things to watch:
Since every object gets its own instance, every class that changes the state of the system, needs to call _context.SaveChanges() (otherwise changes would get lost). This can complicate your code, and adds a second responsibility to the code (the responsibility of controlling the context), and is a violation of the Single Responsibility Principle.
You need to make sure that entities [loaded and saved by a DbContext] never leave the scope of such a class, because they can't be used in the context instance of another class. This can complicate your code enormously, because when you need those entities, you need to load them again by id, which could also cause performance problems.
Since DbContext implements IDisposable, you probably still want to Dispose all created instances. If you want to do this, you basically have two options. You need to dispose them in the same method right after calling context.SaveChanges(), but in that case the business logic takes ownership of an object it gets passed on from the outside. The second option is to Dispose all created instances on the boundary of the Http Request, but in that case you still need some sort of scoping to let the container know when those instances need to be Disposed.
Another option is to not inject a DbContext at all. Instead, you inject a DbContextFactory that is able to create a new instance (I used to use this approach in the past). This way the business logic controls the context explicitly. If might look like this:
public void SomeOperation()
{
using (var context = this.contextFactory.CreateNew())
{
var entities = this.otherDependency.Operate(
context, "some value");
context.Entities.InsertOnSubmit(entities);
context.SaveChanges();
}
}
The plus side of this is that you manage the life of the DbContext explicitly and it is easy to set this up. It also allows you to use a single context in a certain scope, which has clear advantages, such as running code in a single business transaction, and being able to pass around entities, since they originate from the same DbContext.
The downside is that you will have to pass around the DbContext from method to method (which is termed Method Injection). Note that in a sense this solution is the same as the 'scoped' approach, but now the scope is controlled in the application code itself (and is possibly repeated many times). It is the application that is responsible for creating and disposing the unit of work. Since the DbContext is created after the dependency graph is constructed, Constructor Injection is out of the picture and you need to defer to Method Injection when you need to pass on the context from one class to the other.
Method Injection isn't that bad, but when the business logic gets more complex, and more classes get involved, you will have to pass it from method to method and class to class, which can complicate the code a lot (I've seen this in the past). For a simple application, this approach will do just fine though.
Because of the downsides, this factory approach has for bigger systems, another approach can be useful and that is the one where you let the container or the infrastructure code / Composition Root manage the unit of work. This is the style that your question is about.
By letting the container and/or the infrastructure handle this, your application code is not polluted by having to create, (optionally) commit and Dispose a UoW instance, which keeps the business logic simple and clean (just a Single Responsibility). There are some difficulties with this approach. For instance, where do you Commit and Dispose the instance?
Disposing a unit of work can be done at the end of the web request. Many people however, incorrectly assume that this is also the place to Commit the unit of work. However, at that point in the application, you simply can't determine for sure that the unit of work should actually be committed. e.g. If the business layer code threw an exception that was caught higher up the callstack, you definitely don't want to Commit.
The real solution is again to explicitly manage some sort of scope, but this time do it inside the Composition Root. Abstracting all business logic behind the command / handler pattern, you will be able to write a decorator that can be wrapped around each command handler that allows to do this. Example:
class TransactionalCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
readonly DbContext context;
readonly ICommandHandler<TCommand> decorated;
public TransactionCommandHandlerDecorator(
DbContext context,
ICommandHandler<TCommand> decorated)
{
this.context = context;
this.decorated = decorated;
}
public void Handle(TCommand command)
{
this.decorated.Handle(command);
context.SaveChanges();
}
}
This ensures that you only need to write this infrastructure code once. Any solid DI container allows you to configure such a decorator to be wrapped around all ICommandHandler<T> implementations in a consistent manner.
There are two contradicting recommendations by microsoft and many people use DbContexts in a completely divergent manner.
One recommendation is to "Dispose DbContexts as soon as posible"
because having a DbContext Alive occupies valuable resources like db
connections etc....
The other states that One DbContext per request is highly
reccomended
Those contradict to each other because if your Request is doing a lot of unrelated to the Db stuff , then your DbContext is kept for no reason.
Thus it is waste to keep your DbContext alive while your request is just waiting for random stuff to get done...
So many people who follow rule 1 have their DbContexts inside their "Repository pattern" and create a new Instance per Database Query so X*DbContext per Request
They just get their data and dispose the context ASAP.
This is considered by MANY people an acceptable practice.
While this has the benefits of occupying your db resources for the minimum time it clearly sacrifices all the UnitOfWork and Caching candy EF has to offer.
Keeping alive a single multipurpose instance of DbContext maximizes the benefits of Caching but since DbContext is not thread safe and each Web request runs on it's own thread, a DbContext per Request is the longest you can keep it.
So EF's team recommendation about using 1 Db Context per request it's clearly based on the fact that in a Web Application a UnitOfWork most likely is going to be within one request and that request has one thread. So one DbContext per request is like the ideal benefit of UnitOfWork and Caching.
But in many cases this is not true.
I consider Logging a separate UnitOfWork thus having a new DbContext for Post-Request Logging in async threads is completely acceptable
So Finally it turns down that a DbContext's lifetime is restricted to these two parameters. UnitOfWork and Thread
Not a single answer here actually answers the question. The OP did not ask about a singleton/per-application DbContext design, he asked about a per-(web)request design and what potential benefits could exist.
I'll reference http://mehdi.me/ambient-dbcontext-in-ef6/ as Mehdi is a fantastic resource:
Possible performance gains.
Each DbContext instance maintains a first-level cache of all the entities its loads from the database. Whenever you query an entity by its primary key, the DbContext will first attempt to retrieve it from its first-level cache before defaulting to querying it from the database. Depending on your data query pattern, re-using the same DbContext across multiple sequential business transactions may result in a fewer database queries being made thanks to the DbContext first-level cache.
It enables lazy-loading.
If your services return persistent entities (as opposed to returning view models or other sorts of DTOs) and you'd like to take advantage of lazy-loading on those entities, the lifetime of the DbContext instance from which those entities were retrieved must extend beyond the scope of the business transaction. If the service method disposed the DbContext instance it used before returning, any attempt to lazy-load properties on the returned entities would fail (whether or not using lazy-loading is a good idea is a different debate altogether which we won't get into here). In our web application example, lazy-loading would typically be used in controller action methods on entities returned by a separate service layer. In that case, the DbContext instance that was used by the service method to load these entities would need to remain alive for the duration of the web request (or at the very least until the action method has completed).
Keep in mind there are cons as well. That link contains many other resources to read on the subject.
Just posting this in case someone else stumbles upon this question and doesn't get absorbed in answers that don't actually address the question.
I'm pretty certain it is because the DbContext is not at all thread safe. So sharing the thing is never a good idea.
One thing that's not really addressed in the question or the discussion is the fact that DbContext can't cancel changes. You can submit changes, but you can't clear out the change tree, so if you use a per request context you're out of luck if you need to throw changes away for whatever reason.
Personally I create instances of DbContext when needed - usually attached to business components that have the ability to recreate the context if required. That way I have control over the process, rather than having a single instance forced onto me. I also don't have to create the DbContext at each controller startup regardless of whether it actually gets used. Then if I still want to have per request instances I can create them in the CTOR (via DI or manually) or create them as needed in each controller method. Personally I usually take the latter approach as to avoid creating DbContext instances when they are not actually needed.
It depends from which angle you look at it too. To me the per request instance has never made sense. Does the DbContext really belong into the Http Request? In terms of behavior that's the wrong place. Your business components should be creating your context, not the Http request. Then you can create or throw away your business components as needed and never worry about the lifetime of the context.
I agree with previous opinions. It is good to say, that if you are going to share DbContext in single thread app, you'll need more memory. For example my web application on Azure (one extra small instance) needs another 150 MB of memory and I have about 30 users per hour.
Here is real example image: application have been deployed in 12PM
What I like about it is that it aligns the unit-of-work (as the user sees it - i.e. a page submit) with the unit-of-work in the ORM sense.
Therefore, you can make the entire page submission transactional, which you could not do if you were exposing CRUD methods with each creating a new context.
Another understated reason for not using a singleton DbContext, even in a single threaded single user application, is because of the identity map pattern it uses. It means that every time you retrieve data using query or by id, it will keep the retrieved entity instances in cache. The next time you retrieve the same entity, it will give you the cached instance of the entity, if available, with any modifications you have done in the same session. This is necessary so the SaveChanges method does not end up with multiple different entity instances of the same database record(s); otherwise, the context would have to somehow merge the data from all those entity instances.
The reason that is a problem is a singleton DbContext can become a time bomb that could eventually cache the whole database + the overhead of .NET objects in memory.
There are ways around this behavior by only using Linq queries with the .NoTracking() extension method. Also these days PCs have a lot of RAM. But usually that is not the desired behavior.
Another issue to watch out for with Entity Framework specifically is when using a combination of creating new entities, lazy loading, and then using those new entities (from the same context). If you don't use IDbSet.Create (vs just new), Lazy loading on that entity doesn't work when its retrieved out of the context it was created in. Example:
public class Foo {
public string Id {get; set; }
public string BarId {get; set; }
// lazy loaded relationship to bar
public virtual Bar Bar { get; set;}
}
var foo = new Foo {
Id = "foo id"
BarId = "some existing bar id"
};
dbContext.Set<Foo>().Add(foo);
dbContext.SaveChanges();
// some other code, using the same context
var foo = dbContext.Set<Foo>().Find("foo id");
var barProp = foo.Bar.SomeBarProp; // fails with null reference even though we have BarId set.

C# Entity Framework 4.3 DbContext

Im working on a MVC application, and was just wondering.. Should I be using the singleton pattern on my dbcontext object or is it safe to just instantiate one in every controller needed ?
You should not use a singleton pattern. Use one DbContext for one unit of work. The controller seems like a reasonable place to instantiate the context.

Entity Framework 4 ObjectContext GuideLines

I read in a previous article about how to resolve a solution by placing the ObjectContext of my Db in a property within HttpContext.Current.Items["Db"]; This works fantastic, however I have a question. Does this means that every time I use my repository I have to pass the ObjectContext within HttpContext.Current.Items or do I only need to do this when I am creating or updating an entity that has a reference to another entity.
Within my repository classes I have 2 ways of instantiating them, with a ObjectContext and without one in which the ObjectContext is created there within the entity.
You should share one context among all your repositories used in single HTTP request processing. You should also dispose context at the end of request processing. Generally your repository should not be dependent on HttpContext. The best way is to create ObjectContext outside of your repositories and always pass it to their constructor. You can also do that by using some IoC container like Windsor, StructureMap, Ninject or Unity.

Categories

Resources