问题
In my backend service I use unit of work pattern. I was wondering if I'm missing something related to disposing objects.
First, this is the code I have so far, which works. The service just calls a request handler:
[GlobalExceptionHandlerBehaviour(typeof(GlobalExceptionHandler))]
public class CustomerService : ICustomerService
{
public void AddCustomer(AddCustomerRequest request)
{
ObjectFactory.GetInstance<AddCustomerRequestHandler>().Execute(request);
}
}
The request handler looks like:
public class AddCustomerRequestHandler
{
private readonly IUnitOfWork _unitOfWork;
private readonly ICustomerRepository _customerRepository;
public AddCustomerRequestHandler(IUnitOfWork unitOfWork, ICustomerRepository customerRepository)
{
_unitOfWork = unitOfWork;
_customerRepository = customerRepository;
}
public void Execute(AddCustomerRequest request)
{
var customer = new Customer(request.Id, request.CompanyName);
_customerRepository.Add(customer);
_unitOfWork.Commit();
}
}
The unit of work is defined as follows:
public interface IUnitOfWork
{
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory<EfTrackerDbContext> _databaseFactory;
private EfTrackerDbContext _dataContext;
public UnitOfWork(IDatabaseFactory<EfTrackerDbContext> databaseFactory)
{
_databaseFactory = databaseFactory;
}
public EfTrackerDbContext DataContext
{
get { return _dataContext ?? (_dataContext = _databaseFactory.Get()); }
}
public void Commit()
{
DataContext.Commit();
}
}
The EfTrackerDbContext is the actual EF context:
public class EfTrackerDbContext : DbContext, IUnitOfWork
{
public DbSet<Customer> Customers { get; set; }
public virtual void Commit()
{
base.SaveChanges();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>().ToTable("Customer");
}
}
And the DatabaseFactory is like:
public class DatabaseFactory<TContext> : DisposableObject, IDatabaseFactory<TContext> where TContext : DbContext, new()
{
private TContext _dataContext;
public TContext Get()
{
return _dataContext ?? (_dataContext = new TContext());
}
protected override void DisposeManagedResources()
{
if (_dataContext != null)
{
_dataContext.Dispose();
_dataContext = null;
}
}
}
The CustomerRepository:
public interface ICustomerRepository : IRepository<Customer>
{
IQueryable<Customer> Customers { get; }
}
public class CustomerRepository : RepositoryBase<EfTrackerDbContext, Customer>, ICustomerRepository
{
public CustomerRepository(IDatabaseFactory<EfTrackerDbContext> databaseFactory)
: base(databaseFactory)
{
}
public IQueryable<Customer> Customers
{
get { return DataContext.Customers; }
}
}
As you see, everything is injected. Registration looks like:
For<IDatabaseFactory<EfTrackerDbContext>>().HybridHttpOrThreadLocalScoped().Use<DatabaseFactory<EfTrackerDbContext>>();
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
For<ICustomerRepository>().HybridHttpOrThreadLocalScoped().Use<CustomerRepository>();
Now, the question is about disposing the objects. The only place where IDisposable is implemented is DatabaseFactory, where _datacontext is disposed. I guess that is not enough, so I have following questions:
- AddCustomerRequestHandler is injected, so it gets disposed if AddCustomer() service operation ends and garbage collection starts. Is this ok, or should I explicitely call Dispose on the AddCustomerRequestHandler at the end of the AddCustomer() operation and so have it implement IDisposable?
- Should UnitOfWork also implement IDisposable, and do I have to call it explicitely?
- How to dispose the EfTrackerDbContext ?
- Other remarks?
In short, I'm looking for the right way to have everything disposed as soon as the service operation ends.
Thanks for the advice, L
回答1:
Whenever you use something that implements IDisposable you should Dispose it as soon as you don't need it any more. If you use it as a field in a class, implement IDisposable in that class and iterate this process.
PS: If you turn on Code Analysis like this:
you will get some warnings pointing you to this for free :D
来源:https://stackoverflow.com/questions/12476703/how-and-when-to-dispose-my-objects