How and when to dispose my objects?

霸气de小男生 提交于 2020-12-27 03:18:50

问题


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:

  1. 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?
  2. Should UnitOfWork also implement IDisposable, and do I have to call it explicitely?
  3. How to dispose the EfTrackerDbContext ?
  4. 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: enter image description here

you will get some warnings pointing you to this for free :D



来源:https://stackoverflow.com/questions/12476703/how-and-when-to-dispose-my-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!