I'm confused about the proper way to manage my DbContext lifetime using dependency injection in my WinForms application. Right now, I have code that looks like the following
static class Program
{
// This is the main window's controller, which stores all the
// dependencies that are resolved in the composition root and handles
// passing those dependencies to other objects
private static IMainController mainController;
private static void ComposeDependencies
{
UnityContainer container = new UnityContainer();
container.RegisterType<IMyContext, MyContext>();
container.RegisterType<IOrderRepository, OrderRepository>();
container.RegisterType<IOrderService, OrderService>();
mainController = new MainController(
container.Resolve<IOrderService>());
}
}
public class OrderRepository : IOrderRepository
{
private readonly IMyContext context;
public OrderRepository(IMyContext context)
{
this.context = context;
}
}
public class OrderService : IOrderService
{
private readonly IOrderRepository repository;
public OrderService(IOrderRepository repository)
{
this.repository = repository;
}
}
public class MainController
{
private readonly IOrderService orderService;
public MainController(IOrderService orderService)
{
this.orderService = orderService;
}
public void DoSomethingWithAnOrder()
{
FirstTypeOfController controller = new FirstTypeOfController(this.orderService);
// Show window, assign controller, etc.
}
public void DoSomethingElseWithAnOrder()
{
SecondTypeOfController controller = new SecondTypeOfController(this.orderService);
// Show window, assign controller, etc.
}
}
The problem I'm having is that this pattern results in all of my repositories getting created when my program starts, so the MyContext instances stay around through the whole program. So when the database gets updated outside of my program, my program doesn't see the new data because MyContext is using references to the data that it already has loaded.
If this were a web application, then I'd have new dependencies made with every request, but since this is WinForms, I don't understand how to get around this problem while keeping a single composition root and without passing my Unity container all around my program (or having a static reference to it) so that each controller can resolve its own per instance dependencies.
What's the standard solution to this problem, and is there something that I'm doing incorrectly with how/where I'm composing my dependencies or using my DbContext?
I know that MVC is meant more for web applications and something like MVVM or MVP is perhaps more suited to non-web, but those would both have this same problem with a single composition root that only gets called once.
It depends on how you configured your dependency injection, if its Singleton or one instance per scope. I know that on Ninject's DI framework you can specify by using:
//Thread Scope (New instance on each injection)
kernel.Bind<IInterface>.To<ConcreteClass>().InThreadScope();
//Singleton Scope (One instance per application)
kernel.Bind<IInterface>.To<ConcreteClass>().InSingletonScope()
I dont see anything wrong with your implementation, it looks correct. That is right, you are initializing your repositories when your program starts, and that is good, and you keep your contexts for the entire application lifespan. With repositories, you call a method that performs some action against database; in case of fetching data, you always will get the latest data, no matter what, if implemented correctly, unless you would retrieve it on application load and store it somewhere for future access (like global variables, settings as an example).
Related
I wanted to create a background task for my application and in that task I need DbContext to do some operation on data for every 5 seconds.I tried 2 way to get DbContext and it seems like both of them worked but I wanna now what is the difference between them(if there is any)
Here is the first approach
private readonly IServiceScopeFactory _serviceScopeFactory;
public worker(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
private void DoWork(object? state)
{
var scope = _serviceScopeFactory.CreateScope();
var context = scope.ServiceProvider.GetService<ApplicationDbContext>();
}
And this is the second approach that I tried
private void DoWork(object? state)
{
using (var db = new ApplicationDbContext(new DbContextOptions<ApplicationDbContext>()))
{
//do job
}
}
both of them seems working.Isn't both of them disposed and recreated when method called ? what is the difference? which one would you prefer and why?
In general if you use dependency injection for the dbcontext it is scoped for the whole request. That means that using the dbcontext in different classes or methods will be using the same transaction which for example u can after all changes commit with .SaveChanges(). The dependency injection method is also good for making abstractions. If you create interface for your dbcontext then You can make two implementations - one will be your existing dbcontext and the other for example will not use the real database but some data in memory for the development.
If you use the using method then the transaction is within the using brackets and it's not accessible from multiple places but only in the place where it's instantiated and you are also tightly coupled with the framework.
I have an n-tier web application with a Web UserInterface, BusinessLogicLayer and DataAccessLayer. I am looking for the best possible solution to pass my current logged in user's details all the way to the data-access without add it to all my method signatures. The user details are needed for auditing purposes. I believe you can create a context that is available application wide, is there anyone with an example of doing this? I am looking for the best design pattern that will separate my concerns.
Here are two approaches:
First
This approach makes more sense if those other layers actually need to know about the user. For example, they might check permissions or make some decision based on who the user is.
You can create an abstraction or interface to describe what you want those classes to be able to access, something like this:
public interface IUserContext
{
SomeClassContainingUserData GetCurrentUser();
}
I'd define that user data class according to what the consumer class needs instead of just using some existing Customer class just to keep this from getting tightly coupled to your web app.
Now you can inject that class into your other classes:
public class MyBusinessLogicClass
{
private readonly IUserContext _userContext;
public MyBusinessLogicClass(IUserContext userContext)
{
_userContext = userContext;
}
public void SomeOtherMethod(Whatever whatever)
{
var user = _userContext.GetCurrentUser();
// do whatever you need to with that user
}
}
This keeps your other classes testable because it's easy to inject a mock of the interface that returns what you want so you can make sure your class behaves correctly for different types of users.
If your user data comes from HttpContext then your runtime implementation could look roughly like this:
public class HttpUserContext
{
private readonly IHttpContextAccessor _contextAccessor;
public HttpUserContext(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public SomeClassContainingUserData GetCurrentUser()
{
var httpContext = _contextAccessor.HttpContext;
// get the user data from the context and return it.
}
}
That's a rough outline. One consideration is scoping. If all of your objects are scoped per-request then the IUserContext implementation could generate the user data once and store it in a member variable instead of accessing it over and over.
The drawback is having to inject this everywhere, but that's inevitable if those classes need that information.
Second
What if those inner classes don't actually need user information at all? What if you just want to log which users made requests that were handled by those classes? What if you want a separate object to check permissions?
In that case an option would be an interceptor or a wrapper. In its simplest form it could look like this:
public class SomeBusinessClassSecurityInterceptor : ISomeBusinessClass
{
private readonly ISomeBusinessClass _inner;
private readonly IUserContext _userContext;
public SomeBusinessClassSecurityInterceptor(
ISomeBusinessClass inner, IUserContext userContext)
{
_inner = inner;
_userContext = userContext;
}
public void UpdateSomeData(Foo data)
{
if(!CanUpdate())
throw new YouCantUpdateThisException();
_inner.UpdateSomeData(data);
}
private bool CanUpdate()
{
var user = _userContext.GetCurrentUser();
// make some decision based on the user
}
}
If retrieving permissions for a user is more involved, you might want to have an IUserPermissions and inject that instead of IUserContext. Then inject IUserContext into the implemenation of IUserPermissions. At runtime it retrieves the current user and then does its own thing to determine what permissions the user has.
If you've got lots of classes and methods then maintaining separate wrapper classes could become tedious. Another option is to use an interceptor which likely means using a different dependency injection container like Windsor or Autofac. These are especially good for logging.
Using Autofac as an example, that would mean writing a class like this:
public class LoggingInterceptor : IInterceptor
{
private readonly IUserContext _userContext;
private readonly ILogger _logger;
public CallLogger(IUserContext userContext, ILogger logger)
{
_userContext = userContext;
_logger = logger;
}
public void Intercept(IInvocation invocation)
{
var user = _userContext.GetCurrentUser();
_logger.Log(
// some stuff about the invocation, like method name and maybe parameters)
// and who the user was.
// Or if you were checking permissions you could throw an exception here.
invocation.Proceed();
}
}
Then you would tell the container that all calls to the "real" implementation of a given class go through this interceptor (described very well in their documentation.)
If you were checking permissions you could inject IUserPermissions. The interceptor could check for an attribute on the inner method that specifies what permissions are needed and compare that to the current user's permissions.
You can typically write one interceptor and use it with lots of other classes because it doesn't need to know anything about the inner target class. But if you need to you can also write more narrowly-purposed interceptors used just for certain classes.
What's nice is that it gives you a lot of flexibility but doesn't touch the actual interface or implementation of your business logic or data classes. They can focus on their single responsibilities while other classes are configured to log requests made to them or check user permissions.
I'm trying to set the variable DB as global and use anywhere.
My problem is that I'm initialising twice the db. In the base controller and in atributes.
ie:
public class SettingsAttribute : ActionFilterAttribute {
public ApplicationDbContext db = new ApplicationDbContext();
public override void OnActionExecuting(ActionExecutingContext filterContext) {
...
}
and
[Settings]
public class BaseController : Controller {
public ApplicationDbContext db = new ApplicationDbContext();
protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state) {
...
}
I would like to create the var db just once, and access anywhere in the project.
How ca I do this?
Consider using of Dependency Injection pattern. For .NET there is for example Unity container, which implements a lightweight, extensible dependency injection container. Check the List of dependency injection containers for .NET, but it's quite old.
In general, Dependency injection is called Inversion of Control (IoC). That means, your classes, which are using for example your DB class, don't need to be dependent on a specific DB class. Instead, they just require a specific interface. DB class implementing this interface is injected from the outside and your class is decoupled from a specific implementation of DB class.
Some places to start with:
Dependency Injection on Wikipedia.org
Why does one use dependency injection?
An Absolute Beginner's Tutorial on Dependency Inversion Principle, Inversion of Control and Dependency Injection
Dependency Injection in Windows Communication Foundation
What about putting it in another class (an Helper, for instance), and access it like this:
private ApplicationDbContext db = null;
public ApplicationDbContext Db {
get {
if (db == null)
db = new ApplicationDbContext();
return db;
}
}
Best practice in this situation and (similar situations) is to implement a DI/IoC pattern , as #Dawid-Ferenczy mentioned in his answer. if you never worked with it before , it's a little abstract at the beginning but it's very useful in the long run , especially if your objects got complicated. You can search online for articles to learn more about the pattern itself.
#Dawid-Ferenczy mentioned the Unity container, but it's not limited to that , you can use any container you would like (Or even create your own if you need to ).
I personally use Ninject as it has a has a lot of support documentation and i found it easy to implement.
In your case (DB context) i would use Ninject and DI/IoC as follow:
1- Declare an interface for your DB Context DAL:
public interface IModelDBContext
{
//Your methods should go here
}
Your concrete class:
public class ModelDBContext : DbContext,IModelDBContext
{
//Your methods and other stuff here
}
Container part
(Ninject in my case , but you can use any other container)
public class NinjectDependencyResolver : IDependencyResolver
{
//Bunch of initialization and methods
Check out this : [Using ninject in MVC][2].
//Binding piece (Very important)
private void AddBindings()
{
//Context DB Binding
kernel.Bind<IModelDBContext>().To<ModelDBContext>();
//Other binding
}
}
Implementation part:
This is the fun and exciting part. anywhere in your application , if you need to implement your specific DB context you inject it with the constructor and it will be available for you to use:
In your case it will be something like this:
Public YourConcreteClass
{
Private IModelDBContext ModelDB; //Initiate an instance that you will use .
//DI by constructor
public YourConcreteClass(IModelDBContext mDB)
{
ModelDB=mDB;
}
//in the rest of your code you call ModelDB that has access to all of the methods and attributes you might need
}
I am currently trying to get my head around structuremap now that the ObjectFactory static function has been marked as obsolete.
In the long run I have to use this in a MVC and WebApi application. When previously used, a line to a static method was placed in the the global.asax to initialise everything using the ObjectFactory.
ObjectFactory.Initialize{
container.For .....
}
Trying to convert this to the new IContainer approach I have come up with the following however am wondering if I have actually inadvertently implemented this often mentioned Anti-Pattern in my approach.
Static method to return container:
public class StructureMapConfig
{
public static IContainer GetContainer()
{
return new Container(container =>
{
container.For<IUserService>().Use<UserService>();
container.For<IStringService>().Use<StringService>();
container.For<IUserRepository>().Use<UserRepository>();
});
}
}
Userservice's contstructor looks like this:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
private readonly IStringService _stringService;
public UserService(IUserRepository userRepository, IStringService stringService)
{
_userRepository = userRepository;
_stringService = stringService;
}
Finally the initialise (this instance in a console app) looks somthing like this:
private static IUserService _userService;
private static IContainer _container;
static void Main(string[] args)
{
_container = StructureMapConfig.GetContainer();
_userService = _container.GetInstance<IUserService>();
}
So to my questions.
Am I doing anything seriously wrong here
In the UserService, should I be passing the IContainer in and using the object factory to get the instance or should I leave as is.
Is returning the IContainer from the static method the best approach
If this was a MVC app, is it best practice to build this once in the Global.asax or should the controller constructor call the static method every time.
Thanks for any advice.
To go through your questions in order:
Am I doing anything seriously wrong here
No, I don't see anything seriously wrong here. There are a few improvements you could make that I'll talk about shortly.
In the UserService, should I be passing the IContainer in and using
the object factory to get the instance or should I leave as is.
You're correct in injecting UserService over an instance of IContainer. If your controller only requires the UserService then why inject the entire container. Really you only want to inject the bare minimum of what you need to reduce unnecessary coupling and dependencies.
Is returning the IContainer from the static method the best approach
Within the removal of the ObjectFactory then yes, returning an instance of the container via a static method is a common approach for those classes whose creation is not managed via MVC's Dependency Resolution.
If this was a MVC app, is it best practice to build this once in the
Global.asax or should the controller constructor call the static
method every time.
Creating the container in Global.asax.cs is your best approach as it's done once on Application_Start, however see below for my recommendation of using a nested container per http request.
Improvements:-
Take advantage of StructureMap's registries:
Instead of referencing the dependencies directly like this:
public static IContainer GetContainer()
{
return new Container(container =>
{
container.For<IUserService>().Use<UserService>();
container.For<IStringService>().Use<StringService>();
container.For<IUserRepository>().Use<UserRepository>();
});
}
Opt to use StructureMap's registries instead. This way you can group your dependencies (such as MVC specific dependencies or WebAPI specific dependencies, like so:
public class WebsiteRegistry : Registry
{
public WebsiteRegistry()
{
this.For<IUserService>().Use<UserService>();
this.For<IStringService>().Use<StringService>();
this.For<IUserRepository>().Use<UserRepository>();
}
}
Then load your registries like this:
container.Configure(c => {
c.IncludeRegistry<WebsiteRegistry>();
c.IncludeRegistry<TaskRegistry>();
});
HTTP Context bound containers:
Another recommended pattern when using StructureMap with ASP.NET MVC or WebApi (or any HTTP based application) is to use nested containers that are bound to each HTTP request. This basically involves creating a new nested container on each HTTP request and then disposing it at the end of the request. This ensures that dependencies such as session objects, database connections, or UoW contexts are disposed of as soon as the HTTP request is over.
I would recommend taking a look over this article which goes into more detail on the matter and talks about how this can be set up.
This is exactly the same technique that's used in the StructureMap.MVC5 package that's often recommended by StructureMap's creator, Jeremy Miller.
Auto registering dependencies
Instead of registering every dependency with StructureMap manually you can take advantage of StructureMap's auto-registration. You can also specify your own scanning conventions.
I have a layered application with the following projects:
DAL (using EntityFramework with repositories)
DAL.Model (contains the entities, and is referenced by all the others)
Services
UI (in wpf)
The base repository looks like this:
public abstract class RepositoryBase<T> where T : class
{
private readonly MyContext context;
private readonly IDbSet<T> dbSet;
protected RepositoryBase(MyContext dataContext)
{
context = dataContext;
dbSet = context.Set<T>();
}
protected MyContext Context
{
get { return context; }
}
**And a series of virtual methods for Add, Delete, etc.
}
All repositories extend this one, such as:
public class MarketRepository : RepositoryBase<Market>
{
public MarketRepository(MyContext dataContext) : base(dataContext)
{
}
public IEnumerable<Market> GetAllMarkets()
{
return this.Context.Markets.ToList<Market>();
}
}
The services look like this:
public class MarketService
{
IMarketRepository _marketRepository;
public MarketService(IMarketRepository marketRepository)
{
_marketRepository = marketRepository;
}
public IEnumerable<Market> GetAllMarkets()
{
return _marketRepository.GetAllMarkets();
}
}
What I would like to achieve is that the UI layer would only have a reference to the Services layer, the Services layer only with the DAL layer (and all of them to Model, where the entities live) using DI (right now I'm using Unity).
The problem is, in my container in the UI I only want to do this
unity.RegisterType<IMarketService, MarketService>();
and not have to do it as well for the repositories, because then the UI layer would have a dependency on the DAL layer.
I thought about adding a parameterless constructor to the Service classes, like:
public MarketService() : this(new MarketRepository(*What would I put here?)) { }
but then I'm loosing the abstraction that the interface gives, and also I don't know what to do with the MyContext that the repository needs as a parameter; if I pass a new one, then I need to reference the DAL.
Should I change my repositories to create a new MyContext in the constructor, rather than getting it as a parameter?
How can I refactor my architecture to make it work properly and with minimal dependencies?
Well, I belive it is up to the bootstrapper to configure dependencies, in the higher level of the application. As it is usually the UI project, if it needs to reference other assemblies, so be it. If you do not like your UI project managing that, than create a bootstrapper project responsable for getting your app running and separete your UI classes in another one.
Your IoC container should support Dependency Injection using a string from an external configuration file. This way you are not hardcoding the mapping. Structuremap does this quite well, so I am sure other IoCs will.
Adding external dependenices as a parameter when creating an instance is the way to go.
I think you should make yourself more familiar with the different ways to configure Unity, so that the dependencies are resolved.
Could you elaborate why you are creating a repository when using a dependency injection framework?
When configuring DI, you should follow the same pattern - UI bootstrapper initializes Services, Services initialize DAL. (With autofac or ninject you could achiece this using modules. With unity you should emulate modules).
In pseudocode something like
//ui
void UILayer.ConfigureUnity(unity)
{
ServiceLayer.ConfigureUnity(unity)
}
//services
void ServiceLayer.ConfigureUnity(unity)
{
DAL.ConfigureUnity(unity)
unity.RegisterType<IMarketService, MarketService>();
}
//dal
void DAL.ConfigureUnity(unity)
{
unity.RegisterType<IMarketRepository, MarketRespository>();
unity.RegisterType<MyContext, MyContext>(); //not sure exact syntax - just register type for 'new Type()' activator.
}