Entity Framework Unit of Work lifetime - c#

I am trying to learn entity framework and related patterns. While searching I came across the site: http://www.asp.net/mvc...
I checked the patterns, but I could not understand one point. According to my investigations, dbcontex lifetime should be very little because it has in-memory object model and these changes should be persisted to database as fast as possible. If not, there will be conflicts in multi-user scenarios.
When I look at the above tutorial, I see that for every controller there is only one uow defined. I wonder if this means as long as I am on a one page of the site doing CRUD operations I am using the same dbcontext. But shouldn't its lifetime shorter? For example for every action one uow could be defined.
Could somebody please explain the lifetime of uow?

Defining a DbContext as a private class variable vs. defining it as a local variable shouldn't make any difference.
Every time an HTTP request is created, the controller is initialized (as well as any of it's class variables) and the action is called. Instances of ontrollers will not persist between different requests, nor will any instances of DbContext.
Check out this article about why you don't have to worry about the lifetime of a DbContext.
EDIT
I realized a caveat to this answer a few days after I posted it, and I would have felt guilty had I not updated it.
The above statement is true if every action uses your DbContext. If only a few of your actions use it, however, you might be better off using a locally-scoped DbContext instead. This will prevent unnecessary creation of a DbContext class variable any time you call an action that doesn't require usage of it. Will this make your code more efficient? Yes - but insignificantly so - and you'll have to instantiate a DbContext every time you want to use it, which will result in slightly messier code than just having one class-variable at the top.

Each action being called is a new instance of the controller. Just set a breakpoint in your controller constructor and you will see that it is called everytime you make a request to any action on the controller.
Generally a DBContext is scoped per web request in a web application. So if you inject a DBContext into your controller that generally will give you what you need.

In the example given, the controller is taking the responsibility of creating the instance of the DbContext and doing the dispose. A better practice is to let IoC container to take the responsibility of the lifetime control for the instance of DbContext, and implement constructor injection to inject the DbContext into the MVC/WebApi controller.
As for WCF service, my preference is to indicate the below attribute
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
for the service, and also specify the lifetime of the DbContext so that only one DbContext instance would be create per call.
you may need to have some lifetime management if DI will be implemented for WCF service or MVC/WebApi.
Ref: https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx#_Lifetime_Management
This post is also highly recommended for your question.
One DbContext per web request... why?

Related

Is it bad to have a captive dependency on DbContext instance?

Maybe this question has some explanation around but could not find the best solution to this:
I was reading this blog post from Mark Seemann about the captive dependencies and as far as I understand at the end of the post he comes to conclusion never use or at least try to avoid the captive dependencies otherwise there will be troubles (so far is OK). Here is another post from Autofac documentation.
They suggest using captive dependencies only by purpose (when you know what you are doing!). This made me think about a situation I have on my website. I have like 10 services, all of them rely on DbContext for database operations. I think they could easily be registered as InstancePerLifetimeScope if I fix the problem for DbContext not to hold it forever in memory attached to my services. (I am using Autofac in my case). So, I thought a good starting point would be to create all of these as per lifetime instances and the DbContext as instance per request. Then in my services, I would use something like that:
public class MyService
{
private readonly IDbContext _dbContext = DependencyResolver.Current.GetService<IDbContext>();
private MyModel GetMyModel() => Mapper.Map<MyModel>(_dbContext.MyTable.FirstOrDefault());
}
And then in my startup class I have:
builder.RegisterType<ApplicationDbContext>().As<IDbContext>().InstancePerRequest();
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
Does this pattern work correctly, I mean not keeping the dbContext forever attached to any service, so it will be disposed at the end of the request and if it works, is there any performance issue from this line:
private readonly IDbContext _dbContext = DependencyResolver.Current.GetService<IDbContext>();
compared to constructor injection(There are many invocations from dbContext to database so I am afraid to get IDbContext every time I want to use it because it might be resource consuming) ?
The reason I want dbContext to be instance per request and not instance per dependency is that I have implemented the unit of work pattern on top of the dbContext object.
A normal method in my controller would look like:
public ActionResult DoSth()
{
using(var unitOfWork = UnitOfWorkManager.NewUnitOfWork())
{
//do stuff
try
{
unitOfWork.Commit();
return View();
}
catch(Exception e)
{
unitOfWork.RollBack();
LoggerService.Log(e);
return View();
}
}
}
If this works fine then there is another issue I am concerned of. So, if I can make my services as instances per lifetime (except DbContext), is there any issue to apply async-await on every method inside of the services to make them non-blocking methods. I am asking this if there is any issue using async-await for the dbContext instance, so, for example, I would have something like this:
public async MyModel GetMyModel()
{
var result = //await on a new task which will use dbcontext instance here
return Mapper.Map<MyModel>(result);
}
Any advice or suggestion is much appreciated!
I'd approach the issue from a distance.
There are some architectural choices which can make your life easier. In web development it's practical to design your application to have stateless service layer (all the state is persisted in DB) and to fit the one HTTP request, one business operation principle (in other words one service method for one controller action).
I don't know how your architecture looks (there's not enough info in your post to determine) but chances are it meets the criteria I described above.
In this case it's easy to decide which component lifetime to choose: DbContext and service classes can be transient (InstancePerDependency in terminology of Autofac) or per request (InstancePerRequest) - it doesn't really matter. The point is that they have the same lifetime so the problem of captive dependencies doesn't arise at all.
Further implications of the above:
You can just use ctor injection in your service classes without worries. (Anyway, service locator pattern would be the last option after investigating lifetime control possibilities like lifetime scopes and IOwned<T>.)
EF itself implements the unit of work pattern via SaveChanges which is suitable most of the cases. Practically, you only need to implement an UoW over EF if its transaction handling doesn't meet your needs for some reason. These are rather special cases.
[...] is there any issue to apply async-await on every method inside of the
services to make them non-blocking methods.
If you apply the async-await pattern consistently (I mean all async operations are awaited) straight up to your controller actions (returning Task<ActionResult> instead of ActionResult), there'll be no issues. (However, keep in mind that in ASP.NET MVC 5 async support is not complete - async child actions are not supported.)
The answer, as always, is it depends... This configuration can work if:
Your scopes are created within the request boundary. Is your unit of work creating a scope?
You don't resolve any of your InstancePerLifetimeScope services before creating your scope. Otherwise they potentially live longer than they should if you create multiple scopes within the request.
I personally would just recommend making anything that depends on DbContext (either directly or indirectly) InstancePerRequest. Transient would work as well. You definitely want everything within one unit of work to be using the same DbContext. Otherwise, with Entity Framework's first level cache, you may have different services retrieving the same database record, but operating on different in-memory copies if they're not using the same DbContext. Last update would win in that case.
I would not reference your container in MyService, just constructor inject it. Container references in your domain or business logic should be used sparingly and only as a last resort.

What are the practical scenarios to use IServiceCollection.AddTransient, IServiceCollection.AddSingleton and IServiceCollectionAddScoped Methods?

After reading this post I can understand the differences between AddTransient,AddScoped and AddSingleton however, I am unable to see the practical usage of each of them.
My understanding is
AddTransient
Creates a new instance every time when the client asks for it.
services.AddTransient<IDataAccess, DataAccess>();
will return a new DataAccess object every time a client code asks for it. More likely a constructor.
Usage of AddTransient
In cases when we have to access a database to read and update it and destroy the access object (DataAccess) its best to use AddTransient - Not sure about the thread safty.
AddScoped
Creates a new instance for each http web request.
Usage of AddScoped
services.AddScoped<ShoppingCart>(serviceProvider => ShoppingCart.GetShoppingCart(serviceProvider));
this mean each web request will be having its own shopping cart instance which intern means each user / client will be having its own shoping cart instance for that http web request.
AddSingleton
Create single instance for all the http web requests.
Usage of AddSingleton
Found this code in an sample application but I dont understand how it is being useful.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
Can someone please give a decent practical example when to use AddSingleton and check if my understanding of AddTransient and AddScoped is correct?
Your understanding of all 3 scopes is correct.
Transient would be used when the component cannot be shared. A non-thread-safe database access object would be one example.
Scoped can be used for Entity Framework database contexts. The main reason is that then entities gotten from the database will be attached to the same context that all components in the request see. Of course if you plan on doing queries with it in parallel, you can't use Scoped.
Another example of a Scoped object would be some kind of a RequestContext class, that contains e.g. the username of the caller. A middleware/MVC filter can request it and fill out the info, and other components down the line can also request for it, and it will surely contain the info for the current request.
Singleton components are shared always, so they are best for thread-safe components that do not need to be bound to a request. An example would be IOptions, which gives access to configuration settings. An HttpClient wrapper class that uses SendAsync on a single static HttpClient instance would also be completely thread-safe, and a good candidate for being a Singleton.
Note that if you have a Singleton component that depends on a Scoped component, its dependency would get disposed before it. Thus a component cannot depend on another component that has smaller scope than itself.
I've seen the "just use AddTransient<T>()" view, but I don't agree.
Think about memory allocation
I hate allocating things when I don't have to, so if I know I'm creating something that's thread-safe, or that I have explicit documentation that having a singleton instance is the expected usage, then I'm creating a singleton.
AddSingleton()
Here's the ApplicationInsights TelemetryClient instance as a singleton. Their documentation says this works.
telemetryClient = new TelemetryClient(TelemetryConfiguration.Active);
services.AddSingleton<TelemetryClient>(telemetryClient);
In this project I use Azure Table Storage as well, and I've found that creating a CloudTableClient as a singleton works just fine. I don't need to keep creating instances of it for every request.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Configuration.GetValue<string>("storageAccountConnectionString"));
CloudTableClient someTableClient = storageAccount.CreateCloudTableClient();
services.AddSingleton<CloudTableClient>(someTableClient);
In some sense, it's the equivalent of a class's readonly static property, for instance:
public static readonly CloudTableClient cloudTableClient = new CloudTableClient(...);
... there's only one instance of it in the whole application, but by using services.AddSingleton<T>() we get direct access to it using Dependency Injection.
AddScoped()
An example of AddScoped<T>() for me is that I want to embed the JavaScript that I need to get Application Insights into a web page, but I use Content-Security-Policy, so I need to put a nonce on any on-page JavaScript. I have a little bit of code that helps me do it.
services.AddScoped<ApplicationInsightsJsHelper>();
AddTransient()
I haven't found a need to use AddTransient<T>() for anything yet. It could be that I don't think of things that I have to create, every time I need them, as "services"... they're just variables that I new up. In some sense, AddTransient<T>() is a hidden use of the Factory pattern... instead of calling a static MyServiceFactory.Create() function, you have Dependency Injection (effectively) do the same thing for you.

Static Class Persistance in MVC Applications

I have over the last couple of months migrated my Webforms knowledge to MVC knowledge, and I have to say that after originally being an MVC skeptic I am loving MVC and the way it works.
The only thing I am still a bit unclear about is how static classes are persisted in MVC. In Webforms static class values were shared amongst the different clients accessing the application, which could lead to a user overwriting another users values should you decide to use static classes to save user related variables.
My first question is whether or not this is still the case in MVC?
Then my second question is about where to keep the DBContext instance in my MVC application. Currently I have it as a public variable in a static DAL class. The single context is then shared amongst all the clients.
The more I read about this the more I am starting to believe that this is the incorrect approach, but recreating the context inside each controller seems repetitive.
Is there a downside to having the Context in a static class?
The context is supposed to be short-lived, so it might seem repetitive, but yes, create a context inside each controller. Use a single context per request to be precise.
Persisting a single DbContext instance across the lifetime of an application doesn't sound like a good idea to me. I usually use one DbContext instance per Request.
Following are 2 points that you might want to consider while deciding the appropriate lifetime for DbContext in your application:
Re-using the same context for multiple Requests lets you benefit from
the Cached entities and you could save many hits to the Database but
you might then run into performance issues because you could end up
having all your Database entities in memory at some time.
Re-instantiating context too often on the other hand is also not
recommended because it is an expensive operation.
You have to find a balance somewhere between these 2 approaches and for me, instantiating DbContext Per Request works best in most scenarios.
The DbConext is not thread safe, EF allows only one concurrtent operation on the same context. Therefore it is not a good idea to share it across requests.
In the most cases a context per request is the best solution. (Hint: There are some IoC frameworks like autofac whichcan create instances per request)

Unit Of Work + Repository Pattern - one data instance per controller

I don't understand why with Unit Of Work + Repository Pattern I can use only one data instance (which wraps the DbContext and provides repositories with the relevant entities) per controller in MVC. Without the pattern I need to make an instance of DbContext in every action because of the concurrency problem.
Thanks in advance!
You should have one DbContext per request from the user (which make sense if you think about it).
This is not per controller however - if you have it is working this way for you I'd guess you have the lifecyle set up incorrectly on your Inversion of control container.
A few code samples might help.

Singleton in Asp.NET application

In my app, I create a dbcontext for every call and dependency inject it through Ninject.
I've been thinking of creating a singleton class (ContextManager - BaseController would set the context on every request) to make the context available from everywhere, thus allowing all the services to share the same context. This would furthermore make it easy to, for example, disable proxy creating etc. seeing as the context is managed from one place only.
However, seeing as the object is a singleton object the context would be overwritten per each request which won't work for me (I don't want multiple requests sharing a single context).
What would be the best way to do this (how to preferably a single context ONLY in request scope)?
What you're describing is not a Singleton, but a Request-Scoped object. ASP.NET MVC has strong support for dependency injection, and you should allow your DI bindings to determine where the context comes from, rather than instantiating it yourself. Ninject has binding syntax to support this. I think it goes:
Bind<DataContext>().ToSelf().InRequestScope();
As long as you are using good Dependency-Injection patterns consistently, this should cause the same DataContext instance to be passed to every dependency you have within the same request.
The advantage to relying on Dependency Injection for construction of your context is that if you want to change details like disabling change tracking on the context, you can simply change your DI binding to use a custom method or factory, and the rest of your code doesn't have to change at all.
Singleton is not the right approach here, but this is not too hard to implement, by simply instantiating your data context in your controller and injecting it into your service classes, e.g.:
public class SomeController {
private DataContext _context;
private SomeService _service;
public SomeController() {
_context = ...InstantiateContext();
_service = new SomeService(_context);
}
}
This also allows makes it relatively simple to inject your context into your controller if you wish to unit test that. You can also relatively simply dispose of your context by coding this into the dispose method of the controller class (as noted above, a base controller class may be useful).
A singleton carries some persistent state - this is anathema to unit testing and will ultimately give you difficulties in your code.

Categories