I'm using StructureMap to resolve references to my repository class. My repository interface implements IDisposable, e.g.
public interface IMyRepository : IDisposable
{
SomeClass GetById(int id);
}
An implementation of the interface using Entity Framework:
public MyRepository : IMyRepository
{
private MyDbContext _dbContext;
public MyDbContext()
{
_dbContext = new MyDbContext();
}
public SomeClass GetById(int id)
{
var query = from x in _dbContext
where x.Id = id
select x;
return x.FirstOrDefault();
}
public void Dispose()
{
_dbContext.Dispose();
}
}
Anyway as mentioned I'm using StructureMap to resolve IMyRepository. So when, where and how should I call my dispose method?
Instead of adding Dispose to IMyRepository, you could declare IMyRepository like this:
This way, you ensure all repository will call Dispose sometimes, and you can use the C# "using" pattern on a Repository object:
Warning: please note that my views have changed, and you should consider the followimg advise outdated. Please read the update at the end.
While DI frameworks can manage lifetime of objects for you and some could even dispose objects for you after you're done using with them, it makes object disposal just too implicit. The
IDisposable
interface is created because there was the need of deterministic clean-up of resources. Therefore, in the context of DI, I personally like to make this clean-up very explicit. When you make it explicit, you've got basically two options: 1. Configure the DI to return transient objects and dispose these objects yourself. 2. Configure a factory and instruct the factory to create new instances.I favor the second approach over the first, because especially when doing Dependency Injection, your code isn't as clean as it could be. Look for instance at this code:
While this code explicitly disposes the dependency, it could raise some eyebrows to readers, because resources should normally only be disposed by the owner of the resource. Apparently, the
Client
became the owner of the resource, when it was injected.Because of this, I favor the use of a factory. Look for instance at this example:
This example has the exact same behavior as the previous example, but see how the
Client
class doesn't have to implementIDisposable
anymore, because it creates and disposes the resource within theDo
method.Injecting a factory is the most explicit way (the path of least surprise) to do this. That's why I prefer this style. Downside of this is that you often need to define more classes (for your factories), but I personally don't mind.
RPM1984 asked for a more concrete example.
I would not have the repository implement
IDisposable
, but have a Unit of Work that implementsIDisposable
, controls/contains repositories and have a factory that knows how to create new unit of works. With that in mind, the above code would look like this:In the design I use, and have described here, I use a concrete
NorthwindUnitOfWork
class that wraps anIDataMapper
that is the gateway to the underlying LINQ provider (such as LINQ to SQL or Entity Framework). In sumary, the design is as follows:INorthwindUnitOfWorkFactory
is injected in a client.NorthwindUnitOfWork
class and injects a O/RM specificIDataMapper
class into it.NorthwindUnitOfWork
is in fact a type-safe wrapper around theIDataMapper
and theNorthwindUnitOfWork
requests theIDataMapper
for repositories and forwards requests to submit changes and dispose to the mapper.IDataMapper
returnsRepository<T>
classes and a repository implementsIQueryable<T>
to allow the client to use LINQ over the repository.IDataMapper
holds a reference to the O/RM specific unit of work (for instance EF'sObjectContext
). For that reason theIDataMapper
must implementIDisposable
.This results in the following design:
The
NorthwindUnitOfWork
is a concrete class that contains properties to specific repositories, such asCustomers
,Orders
, etc:What's left is an concrete implementation of the
INorthwindUnitOfWorkFactory
and a concrete implementation of theIDataMapper
. Here's one for Entity Framework:And the
EntityFrameworkDataMapper
:You can find more information about this model here.
UPDATE December 2012
This an an update written two years after my original answer. The last two years much has changed in the way I try to design the systems I'm working on. Although it has suited me in the past, I don't like to use the factory approach anymore when dealing with the Unit of Work pattern. Instead I simply inject a Unit of Work instance into consumers directly. Whether this design is feasibly for you however, depends a lot on the way your system is designed. If you want to read more about this, please take a look at this newer Stackoverflow answer of mine: One DbContext per web request…why?
If you want to get it right, i'd advise on a couple of changes:
1 - Don't have private instances of the data context in the repository. If your working with multiple repositories then you'll end up with multiple contexts.
2 - To solve the above - wrap the context in a Unit of Work. Pass the unit of work to the Repositories via the ctor:
public MyRepository(IUnitOfWork uow)
3 - Make the Unit of Work implement IDisposable. The Unit of Work should be "newed up" when a request begins, and therefore should be disposed when the request finishes. The Repository should not implement IDisposable, as it is not directly working with resources - it is simply mitigating them. The DataContext / Unit of Work should implement IDispoable.
4 - Assuming you are using a web application, you do not need to explicitly call dispose - i repeat, you do not need to explicitly call your dispose method. StructureMap has a method called
HttpContextBuildPolicy.DisposeAndClearAll();
. What this does is invoke the "Dispose" method on any HTTP-scoped objects that implement IDisposable. Stick this call inApplication_EndRequest
(Global.asax). Also - i believe there is an updated method, called ReleaseAllHttpScopedObjects or something - can't remember the name.