Question

In the simplified example below I have a DataContext and Repository which I think is defined in a fairly reasonably way:

public interface IUnitOfWork 
{
   int SaveChanges();
}

public class DataContext : DbContext, IUnitOfWork 
{
    public DbSet<Car> Cars { get ; set; }
}

public interface ICarsRepository 
{
    Car Find(int id);
    void Add(Car car);
}

public class SqlCarsRepository : ICarsRepository 
{
    private DataContext  _context;
    public SqlCarsRepository(DataContext context)
    {
       _context = context;
    }

    public Car Find(int id) 
    {
        return _context.Cars.Find(id);
    }

    //etc
}

I am struggling to work out how to use DI and the abstract factory pattern to achieve what I would like. In an MVC application this would be easy to setup - the Controller would require instances of implementations of IUnitOfWork and ICarsRepository in its constructor. I could configure the container to give me the same DataContext instance per Http request, using a different controller factory. Somehow it seems that here the disposable dependencies are disposed correctly.

However I would like to use the same repository within a windows service. This is multi threaded and each thread when started needs to have access to its own repository, and each thread should have its own DataContext / UnitOfWork. But I don't know how to do this:

  • The composite root of the application is when the service starts, so dependencies cannot be resolved for each thread then (the threads are started on demand).
  • I'm not sure how I can use the abstract factory pattern. The thread needs instances of IUnitOfWork and ICarsRepository but sharing the same DataContext. I can make an abstract factory to create these both in one call, and pass that into the thread, but then I don't know how to dispose of the DataContext. I don't want the thread to have to care that the dependencies to the implementation of ICarsRepository it are disposable. I definitely don't want the thread to know that the ICarsRepository has a a dependency on DataContext because then it seems pointless having an interface- the thread could just depend on SqlCarsRespository.
  • I don't want to make SqlCarsRepository disposable and have it dispose the DataContext because there may be others using the DataContext, and it didn't create it in the first place.
  • I thought that I could create a CarsService which hides the IUnitOfWork and ICarsRepository (and get instances of that using abstract factory), but I still then don't know how to dispose of the DataContext dependency

What is the best way to do what I am attempting?

Was it helpful?

Solution

so dependencies cannot be resolved for each thread

They can, and in fact, they should. You should resolve a new object graph at the beginning of each thread. Not doing this, means that you can only use thread-safe dependencies, which isn't the case in your situation.

I'm not sure how I can use the abstract factory pattern

I think at first, try to define your DataContext as Per Web Request in your MVC application and as Per Lifetime Scope (or whatever available in the container you use) in your windows service. In your windows service, each thread will get it's own lifetime scope. Defining a scope often allows you to let instances be disposed when the scope ends.

I don't want the thread to have to care that the dependencies to the implementation of ICarsRepository it are disposable

Your thread should care about this, but your business logic shouldn't. When starting up new threads, you will have to have some infrastructure code that allows starting and ending a scope, and resolving and using the root type of the graph. This code should be part of your composition root, so the rest of the application should be oblivious about this. If you registered some types with a Per Lifetime Scope (or some other explicit lifetime), your container will know when to dispose the instances. The infrastructure code only has to tell the container, that the scope has ended.

I don't want to make SqlCarsRepository disposable

The SqlCarsRepository should depend on an interface that does not implement IDisposable, and in that case there is nothing to dispose. It should be the container responsible of disposing the DataContext, and with the proper registration you can do this.

What is the best way to do what I am attempting?

Your design sounds reasonable, but here are some other SO questions, that might give you more to work with:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top