My application uses Entity Framework. Since I want my DbContext to be reused across a single request, I registered it as Lifestyle.Scoped, as shown below:
container.Register<MyDbContext>(Lifestyle.Scoped);
Other classes get this MyDbContext injected. As example, see the following repository:
ApplicationsRepository is:
public class ApplicationsRepository : IApplicationsRepository
{
private readonly MyDbContext _dbContext;
public ApplicationsRepository(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public void Save()
{
_dbContext.Save();
}
public Application GetByName(string appName)
{
var dbApplication = _dbContext.APPLICATIONS.FirstOrDefault(a => a.NAME == appName);
return ApplicationMapper.MapApplicationFromAPPLICATIONS(dbApplication);
}
}
But there are countless other classes that either take a dependency on MyDbContext. Other classes might not depend on MyDbContext directly, but do get injected with a class that does depend on MyDbContext.
My questions is: what kind of lifestyle management should I use for these classes and how implements it?
There are 3 basic lifestyles to choose from, Transient, Scoped and Singleton, as you already learned by reading this.
Which lifestyle to choose for a particular component, depends on several factors:
Whether or not the component can be used safely across requests/threads
Whether or not the component contains state that needs to be shared across threads
The lifestyle of the component's dependencies.
First of all, the lifestyle your component needs is a choice you need to make based on how that component is designed. Some components simply can't be reused and should always be re-created when requested. This typically holds for framework types such as MVC Controllers. Although there is typically one controller per request, it is possible to request other controllers and this requires new instances to be created. This is equivalent to the Transient lifestyle.
Other components or classes that you register need to be reused. Unit of Work implementations such as Entity Framework's DbContext will typically need to be reused for the duration of a complete request. You can read a detailed discussion about why you want to reuse a DbContext here. This is equivalent to the Scoped lifestyle.
Other components are completely stateless or immutable and can be reused by all threads in the application in parallel without any trouble. Other components might be statefull or mutable, but are designed with thread-safety in mind. They might implement an application-wide cache that needs to be updated, and access to the component is protected with locks. This means you only have one instance reused throughout the application. This is equivalent to the Singleton lifestyle.
Dependencies however complicate lifestyle choice of a component, because a component's lifestyle should never be longer than any of its dependencies. Failing to obey to this rule, causes Captive Dependencies, or Lifestyle Mismatches as Simple Injector calls them.
This means that even if you determined a component to be eligible to be a Singleton, it can only be as long as its shortest dependency. In other words, if the component has a Scoped Dependency, it itself can only be either Scoped or Transient. Simple Injector will detect if you misconfigure this.
This does mean however that the choice you make for a component, does propagate up the call stack to the component's consumers.
In general, this results in a structure where the leaf components in an application's object graphs are Scoped and Singleton, while the root types are Transients. If you are structuring your object graphs in this way, you are following the Closure Composition Model.
There is an alternative DI Composition Model, and it is called the Ambient Composition Model. When practicing this model you, for the most part, keep state out of your components, and instead store state in Ambient State, which is controlled by the Composition Root. Both composition models have their advantages and disadvantages.
Related
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.
In my application I have many services with I use the following pattern:
In the same file as the interface I define a static factory method which is controlled by the IoC container as follows:
public interface ISomethingService {
Task DoSomethingAsync(int id);
}
public class SomethingServicFactory : ServiceFactory<ISomethingService > { }
public class ServiceFactory<T>
{
public static Func<T> CreateClosure;
public T GetDefault() => CreateClosure();
}
After creating and configuring the IoC container:
SomethingServicFactory .CreateClosure = () =>
Container.GetInstance<ISomethingService >();
Later in my application when I need a SomethingService:
var somethingService= new SomethingService().GetDefault();
This allows me to defer creation until the last moment yet still control the service creation using the container. I just started using SimpleInjector.
More importantly it allows me to create an instance of the service and easily pass it parameters while giving control to the IoC.
A great example where this pattern helps me is in a WPF XAML instantiated user control that needs to populate data (i.e. lookup values from a database). In the code behind I am able to easily create a DbContext and get data from the database. However, I have come to use it throughout the application as well.
I am concerned that I am missing a significant design/architecture problem by using this pattern and I am looking for comments on this pattern by IoC experts.
Your design exposes the following code smells and anti-patterns:
Temporal Coupling: Your CreateClosure property forces you to initialize your service factory after its creation. When you forget this, the application will fail at runtime. Temporal Coupling is a code smell.
Ambient Context: The CreateClosure acts as an Ambient Context (which is much like the Singleton design pattern, but with the ability to change the value using a static method or property). This causes a class's dependencies to be hidden, instead of 'statically declared' using the class's constructor. In Dependency Injection in .NET 2nd edition, we consider Ambient Context an anti-pattern (see chapter 5).
Dependency Inversion Principle violation: Your factories are concrete classes, while the DIP promotes talking to interfaces. As a result, your code becomes strongly coupled and hard to test.
Abstract Factories are a code smell: When applying Dependency Injection, the usefulness of factories evaporates. Especially the idea of having a factory for every abstraction in your application is an absolute no-no.
Instead, with Dependency Injection, everything becomes much easier: When we apply Constructor Injection, we can simply inject ISomethingService into its consumers. This:
Makes it clear what dependencies a class has, by looking at the constructor
Allows the DI container to compose the object graph for you and do analysis and diagnostics on the graph
Allows the container to manage lifetime of objects
Removes the need for having factories (since the container will take that role)
Reduces the number of dependencies a class has. Instead of needing 2 (one for the factory and one for the service), you only need one (for the service).
I'm using simple injector 3.0.4
I have a service that with a lifestyle of scoped dependent on a service which has a lifestyle of transient.
When I call container.Verify() I get a diagnostic error about lifestyle mismatch.
The transient service causing the issues is injected into other transient services so before I go ahead and make my whole project scoped I need to ask. Why is a dependency from a scope of any lifestyle to transient an issue? Transients are newed up fresh each time they are injected so nothing else can interfere with it. In essence the lifetime of a transient object is governed by the service it is injected into.
Also I have already read the documentation on this subject from here, and I do understand why you wouldn't want a singleton dependent on a scoped service for instance but surely a dependency on transient is always safe?
Transients are newed up fresh each time they are injected so nothing else can interfere with it.
Transients are newed up every time you request them from the container, but once they are injected into a component, they will stick around for as long as that component lives. So if the consuming component is a singleton, this means that it will drag along all its dependencies, making them practically singletons as well. This behaviour becomes obvious when you look at how you would typically implement dependency injection:
public class SomeComponent
{
private readonly ILogger logger;
private readonly IService service;
public SomeComponent(ILogger logger, IService service) {
this.logger = logger;
this.service = service;
}
}
As you can see, the dependencies are stored in private fields of the component, will cause them to stay alive for as long as SomeComponent lives and SomeComponent will keep using the same dependencies.
In essence the lifetime of a transient object is governed by the service it is injected into.
Exactly; a component's lifestyle will be at least as long as its consumer. However, a dependency can have multiple consumers with different lifestyles, making it really hard to see how long the dependency will live. When injected into consumer 1 it might live for the duration of the request, while another instance of that dependency, injected into consumer 2, will live for as long as the application does.
Just as scoped instances, transient registrations are typically not thread-safe; otherwise you would have registered them as singleton. Keeping transients alive for a longer period of time, can obviously cause concurrency bugs or bugs related to stale data. This is why Simple Injector disallows this by default and throws an exception.
You might be confused by how Autofac defines its lifestyles, compared to Simple Injector. Autofac does not contain a Transient lifestyle. Instead it has an InstancePerDependency lifestyle. Technically this is the same as transient, but the intent is very different. With InstancePerDependency you say: "This component is intended to live as long as its consumer, whatever that lifestyle might be". There might be cases where this makes sense, but by doing this you are actually ignoring the elephant in the room and I've seen the lack of detection to be a common source of bugs. In most cases, if you don’t care about a components lifestyle, it means it should be registered as singleton – not InstancePerDependency.
The reason that Simple Injector doesn't allow transients to be injected into scoped instances is because scoped instances as well can live for a long time (depending on the application) and you can't always assume that transients can safely be injected into scoped consumers.
In the end it is all about communicating the intent of your code. In case a component is stateless or thread-safe, you should register it as singleton. It it's not thread-safe, you register it as scoped or transient. This makes it clear to anyone who reads the configuration how he should handle such component AND it allows Simple Injector to detect any misconfigurations for you.
While Simple Injector detects misconfigurations for you, I came to the conclusion that your DI configuration can be simplified considerably when your system is designed around object graphs that consist purely of singleton components. I expressed these thoughts here. This will remove many of the complexities we face when working with dependency injection, and even exposes SOLID principles violation even more quickly than DI by itself already does.
before I go ahead and make my whole project scoped
That is something I would not advice to do. You would typically see that only some of the 'leaf components' in your application are scoped (such as DbContext). Those scoped components don't depend on many other components. The components that you write yourself should typically be stateless and don't need any caching. So in case making the object graphs singleton is (not yet) an option, I would typically make as much of the object graph transient, and only those few leaf components scoped. Since transients can safely depend on scoped instances, everything will work as expected.
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.
I'm trying to instantiate a SecondViewModel from a MainViewModel injecting in this second one paramaters that are services registered in the IoCContainer and objects from the MainVM.
The code is something of this kind:
class MainViewModel
{
public MainViewModel()
{
}
private string message = "the message";
public string Message { get; set; }
}
class SecondViewModel
{
public SecondViewModel(IService service, string message)
{
}
}
now, i know i can make the IoC Container inject a SecondViewModelFactory (that carries the service instance) into the MainViewModel, so it can create the SVM through it, but what if the implementation of IService is very heavy and i don't want to instantiate it but when i really need it.
And what if i have to instantiate other ViewModels in a similar way? Do I have to create tons of VMFactories and constructor's parameters?
And in case I use a generic ViewModelFactory, it would need to be instantiated passing all the services needed by every ViewModel I have, regardless if they will be created or not.
Do you know any better solution to my case?
In general, the creation of services should not be heavy. Their constructor should do nothing more than storing the incoming dependencies. If it uses some heavy resources in the background, they shouldn't be accessed through the constructor. This keeps the constructor simple (prevents you from having to test it) and allows the object graph to be composed very rapidly.
If there is really no way around this, there are basically two patterns you can apply:
1. Factories
You can inject a factory to delay the creation of a type. Factories are also useful when objects are created that should be controlled explicitly (for instance, instances that should be disposed as soon as possible). There are several ways of creating factories. Some people like to inject Func<T> or Lazy<T> dependencies into their services, but I find this too implicit. I rather inject an ISomeServiceFactory, since I find this more readable. Downside is that you need to define a new interface for this. However, if you find yourself having many factory interfaces, you probably have a problem in your design anyway.
2. Proxies
Instead of creating a factory, you can hide the service behind a proxy. This proxy can implement the same interface as the service and will do the delayed execution for you. This prevents you from letting the application take a dependency on a different interface (an IServiceFactory or Lazy<T> for instance). Especially Lazy<T> leaks details about the creation into the consumer of such a dependency. You can still inject a Lazy<T> into this proxy, if that's convenient. That's not a problem. That proxy would typically be part of your composition root and the rest of your application would still be dependend on your IService and not your Lazy<IService>.
Please be aware that the use of factories, proxies and lazy initiation does complicate the wiring of the container. So don't use if unless you measured that you really need it. They complicate things, because of the indirection, which makes it harder to follow interlectually. And they make it harder to verify your configuration using automated tests. For more information about verifying your container, take a look here and here.
Most IoC Containers supports Lazy dependency to with Lazy<> to avoid creating expensive class immediately.
So in your code, you can make lazy for your expensive IService:
class SecondViewModel
{
public SecondViewModel(Lazy<IService> service, string message)
{
}
}
You can use some popular IoC Containers and see how they support lazy loading: Autofac or NInject