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.
Related
I have a web application with its own dbcontext (context1), and I've a Razor class library with another dbcontext (context2). Ideally I should have a single db context...
The problem i have is when some tables "overlap", e.g. context1 contains entity companies, and context2 contains entity users, yet there mayb be a relationship between companies and users.
Is there a way i can ditch context2 from my CL and somehow inject context1 into my class library?
Or perhaps there is a way i can inherit context2 to context1?
Alternatively, if i keep the two contexts, can i keep the from "overlapping", e.g create a view to allow navigation properites between the two contexts? (just thinking out loud now)
Any advice is much appreciated.
Thanks
Whether you have one context definition or two isn't really the issue, it will be how any instance of a DbContext is scoped and whether a single reference can be shared across the two blocks of code.
For instance if I have some code in an MVC project that is doing something like:
using (var context = new AppContext())
{
var myEntity = context.Entities.Single(x => x.EntityId = entityId);
SomeService.DoSomething(myEntity);
}
and a service library doing something like:
public void DoSomething(AppEntity someEntity)
{
using(var context = new AppContext())
{
someEntity.Status = "DidSomething";
context.Attach(someEntity);
context.Entity(someEntity).State = EntityState.Modified;
context.SaveChanges();
}
}
or the like, then you're probably shaping up for a world of discomfort tracking down stale state related issues. Both blocks of code can be referring to the same DbContext type but different DbContext instances which means that the controller's DbContext reference may not reflect, or be tracking entities that the other library context had committed.
As a general rule, an entity should not leave the scope of the DbContext instance that spawned it. Any entity that does should be considered detached, but if it is not explicitly detached from a DbContext instance, this can lead to errors down the road depending on how long-lived the DbContext that spawned it is. If one assembly references the second assembly then you can use Dependency Injection and an IoC container to manage a lifetime scope of a single DbContext instance across calls, or you can use a Unit of Work provider to provision a DbContext and manage the lifetime of that DbContext. This way, when your library is referenced by MVC, it shares a DbContext instance when called, but if called via another means, it resolves a suitable DbContext instance for entities received from that scenario.
For larger systems it can be prudent to use separate DbContext definitions and simplified entity definitions. Smaller, simpler, short-lived DbContexts operate more efficiently when querying/tracking entities. For services that may get called frequently to operate against data, it can be far better to have a simplified entity against a smaller DbContext. Fetch the entity, inspect, modify, and commit rather than trying to attach, modify, and commit using a full-size entity on a full size DbContext instance. Models like this would use minimum-sized payloads (DTOs) rather than entities as payloads. Callers would receive an indication that their scoped entities should be refreshed or not.
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.
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.
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.
I am new to Entity Framework 4.0, using it with C#, and currently experimenting with its features.
What I noticed is that, like with most similar ORMs, it relies on an Context object to deal with the data-manipulation and CRUD statements generation done on the generated entities.
This means that if I want to save the changes back to the database, I always need to be able to have access to a reference to the ObjectContext that has instanciated the entities.
It is fine and all if the context has been created in an accessable scope (same method, for example), but what if I pass an entity or and entity set to a method and want this method to save the changes? It looks like the only easy way is to pass the ObjectContext along with the parameters.
Another solution would be placing the ObjectContext in some sort of global variable.
Needless to say, I find styling and maintainability issues to both of these approaches.
In short, the best way I can imagine is getting a reference to the ObjectContext from the entity or entity set.
I know that it isn't possible by default.
I have found a method showing adding an extension method to get the ObjectContext from the entity. However, it only works for entities with relationships and calling this method is expensive according to the author.
I was thinking about maybe modifying the T4 template to add a Context property to all my entities and fill it automatically on entities' instanciation.
I have already modified T4 template once to have Entity Framework enforce Max Length on my generated classes (by following Julie Lerman's Programming Entity Framework 4 book).
I can't say I really enjoy the T4 syntax so far, but if that's the best/only way, so be it...
Has anyone already done so and what would be the best way to handle this and willing to share his T4 template or explain what are the best partial methods or events to hook into to get this done?
Is there any major downside in using such an approach?
I am thinking that having so many references to the ObjectContext may hinder/delay its ability to be recollected by the GC if some of my entities remain in scope but I actually have no use anymore for the ObjectContext.
Many thanks.
If you need to pass object context as parameter together with your entities you are doing something wrong.
Usually context is needed only in well defined layer. All classes from this layer which requires context to their logic can receive the context through some specialized class - context provider (it can also be called service locator). Context provider will hold current context instance in some storage - you can create your own or you can store it per thread, per http request, etc.
If they need more then one context instance in your classes you can modify your provider to work also as factory.
Another common approach is combined with dependency injection. You will pass the context to your classes through the constructor (or property) and you will have some bootstraper code which will do all necessary initialization for you (create required instances and pass all dependencies into them). Again you can pass a context or a factory. This is usually used together with IoC containers which will do the plumbing for you.
Once you have this infrastructure prepared you can pass your entity to the any initialized class from that layer and it will have the context available.