Service & UnitOfWork

Aug 17, 2014 at 10:50 AM
I'm a bit confused with creating different services and understanding how the unit of work comes in to play.

Are both examples below in essence the same? I've created different services to inject into controllers where ever I need them but I'm a bit confused over the unit of work. The IService & Service are using that in the Repository.Pattern project. I feel that if don't use a unit of work somewhere I could be prone to not open/close the database connections properly. Do I need to use the unit of work somewhere? If so where?

I have this in my UnityConfig.cs
.RegisterType<ICustomerService, CustomerService>()
In my CustomerController.cs I have
private readonly ICustomerService _customerService;

public CustomerController(ICustomerService customerService)
{
       _customerService = customerService;
}

public ActionResult Index(int? page)
{
      var pageNumber = page ?? 1;
      const int pageSize = 20;

      int totalCustomerCount;

      var customers = _customerService.ODataQueryable();
  
      ViewBag.Customers = new StaticPagedList<Customer>(customers, pageNumber, pageSize, totalCustomerCount);

      return View();
}
In your example you have
private readonly IUnitOfWork _unitOfWork;

public CustomerController(IUnitOfWork unitOfWork)
{
       _unitOfWork = unitOfWork;
}

public ActionResult Index(int? page)
{
      var pageNumber = page ?? 1;
      const int pageSize = 20;

      int totalCustomerCount;

      var customers = _unitOfWork.Repository<Customer>().Query(....).GetPage(....);
  
      ViewBag.Customers = new StaticPagedList<Customer>(customers, pageNumber, pageSize, totalCustomerCount);

      return View();
}
Coordinator
Aug 17, 2014 at 4:57 PM

UnitOfWork is only needed to commit work when there is actually work that needs to take place e.g. inserts, updates, deletes. For reads there is no work to be commited, again so, no UnitOfWork required.


Aug 17, 2014 at 7:14 PM
What if my CustomerService did have CRUD?

Does the Service (in your examples) approach require me to have a UnitOfWork? If so how can I wrap your current Service class to use an UnitOfWork? At the moment the Service class is just implementing an IService using the IRepositoryAsync.
Coordinator
Aug 17, 2014 at 8:46 PM

Simply inject your service with IUnitOfWork.


Aug 17, 2014 at 11:59 PM
Why doesn't the main Service class in your example just by default just have a IUnitOfWork in there?

Do you mean something like this?
public class CustomerService : Service<Customer>, ICustomerService
{
      private readonly IRepositoryAsync<Customer> _repository;
      private readonly IUnitOfWork _unitOfWork;
        
      public CustomerService(IRepositoryAsync<Customer> repository, IUnitOfWork unitOfWork) : base(repository)
     {
              _repository = repository;
              _unitOfWork = unitOfWork;
      }
}
Coordinator
Aug 20, 2014 at 6:20 AM
  1. Teams have expressed, that they aren't always going to need IUnitOfWork in there services, therefore we aren't injecting it out of the box, the framework is designed to easily be extended, so you can simply add IUnitOfWork to Service.Pattern.Service.cs.
  2. Yes, that is correct way to inject IUnitOfWork.
Marked as answer by lelong37 on 8/19/2014 at 10:20 PM
Aug 21, 2014 at 11:57 AM
If I do a select query like in your example
        public async Task<ActionResult> Index()
        {
            return View(await _customerService.GetAsync());
        }
or another example
var customers =
            unitOfWork.Repository<Customer>()
                .Query()
                .Include(i => i.CustomerDemographics)
                .OrderBy(q => q
                    .OrderBy(c => c.ContactName)
                    .ThenBy(c => c.CompanyName))
                .Filter(q => q.ContactName != null)
                .GetPage(pageNumber, pageSize, out totalCustomerCount);
How can you ensure that after the query has taken place, that the SQL connection is closed and not left open? Does the Entity Framework just take care of this?
Coordinator
Aug 21, 2014 at 7:40 PM