title: Unit of work + repository + service layer with dependency injection
body: <p>I am designing a web application and a windows service and want to use the unit of work + repository layer in conjunction with a service layer, and I am having some trouble putting it all together so that the client apps control the transaction of data with the unit of work.</p>
  
  <p>The unit of work has a collection of all repositories enrolled in the transaction along with commit and rollback operations</p>
  
  <pre><code>public interface IUnitOfWork : IDisposable
  {
      IRepository&lt;T&gt; Repository&lt;T&gt;() where T : class;
      void Commit();
      void Rollback();
  }
  </code></pre>
  
  <p>The generic repository has operations that will be performed on the data layer for a particular model (table)</p>
  
  <pre><code>public interface IRepository&lt;T&gt; where T : class 
  {
      IEnumerable&lt;T&gt; Get(Expression&lt;Func&lt;T, bool&gt;&gt; filter = null, IList&lt;Expression&lt;Func&lt;T, object&gt;&gt;&gt; includedProperties = null, IList&lt;ISortCriteria&lt;T&gt;&gt; sortCriterias = null);
      PaginatedList&lt;T&gt; GetPaged(Expression&lt;Func&lt;T, bool&gt;&gt; filter = null, IList&lt;Expression&lt;Func&lt;T, object&gt;&gt;&gt; includedProperties = null, PagingOptions&lt;T&gt; pagingOptions = null);
      T Find(Expression&lt;Func&lt;T, bool&gt;&gt; filter, IList&lt;Expression&lt;Func&lt;T, object&gt;&gt;&gt; includedProperties = null);
      void Add(T t);
      void Remove(T t);
      void Remove(Expression&lt;Func&lt;T, bool&gt;&gt; filter);
  }
  </code></pre>
  
  <p>The concrete implementation of the unit of work uses entity framework under the hood (DbContext) to save the changes to the database, and a new instance of the DbContext class is created per unit of work</p>
  
  <pre><code>public class UnitOfWork : IUnitOfWork
  {
      private IDictionary&lt;Type, object&gt; _repositories;
      private DataContext _dbContext;
      private bool _disposed;
  
      public UnitOfWork()
      {
          _repositories = new Dictionary&lt;Type, object&gt;();
          _dbContext = new DataContext();
          _disposed = false;
      }
  </code></pre>
  
  <p>The repositories in the unit of work are created upon access if they don't exist in the current unit of work instance. The repository takes the DbContext as a constructor parameter so it can effectively work in the current unit of work</p>
  
  <pre><code>public class Repository&lt;T&gt; : IRepository&lt;T&gt; where T : class
  {
      private readonly DataContext _dbContext;
      private readonly DbSet&lt;T&gt; _dbSet;
  
      #region Ctor
      public Repository(DataContext dbContext)
      {
          _dbContext = dbContext;
          _dbSet = _dbContext.Set&lt;T&gt;();
      }
      #endregion
  </code></pre>
  
  <p>I also have a service classes that encapsulate business workflow logic and take their dependencies in the constructor.</p>
  
  <pre><code>public class PortfolioRequestService : IPortfolioRequestService
  {
      private IUnitOfWork _unitOfWork;
      private IPortfolioRequestFileParser _fileParser;
      private IConfigurationService _configurationService;
      private IDocumentStorageService _documentStorageService;
  
      #region Private Constants
      private const string PORTFOLIO_REQUEST_VALID_FILE_TYPES = "PortfolioRequestValidFileTypes";
      #endregion
  
      #region Ctors
      public PortfolioRequestService(IUnitOfWork unitOfWork, IPortfolioRequestFileParser fileParser, IConfigurationService configurationService, IDocumentStorageService documentStorageService)
      {
          if (unitOfWork == null)
          {
              throw new ArgumentNullException("unitOfWork");
          }
  
          if (fileParser == null)
          {
              throw new ArgumentNullException("fileParser");
          }
  
          if (configurationService == null)
          {
              throw new ArgumentNullException("configurationService");
          }
  
          if (documentStorageService == null)
          {
              throw new ArgumentNullException("configurationService");
          }
  
          _unitOfWork = unitOfWork;
          _fileParser = fileParser;
          _configurationService = configurationService;
          _documentStorageService = documentStorageService;
      }
      #endregion
  </code></pre>
  
  <p>The web application is an ASP.NET MVC app, the controller gets its dependencies injected
  in the constructor as well. In this case the unit of work and service class are injected. The action performs an operation exposed by the service, such as creating a record in the repository and saving a file to a file server using a DocumentStorageService, and then the unit of work is committed in the controller action.</p>
  
  <pre><code>public class PortfolioRequestCollectionController : BaseController
  {
      IUnitOfWork _unitOfWork;
      IPortfolioRequestService _portfolioRequestService;
      IUserService _userService;
  
      #region Ctors
      public PortfolioRequestCollectionController(IUnitOfWork unitOfWork, IPortfolioRequestService portfolioRequestService, IUserService userService)
      {
          _unitOfWork = unitOfWork;
          _portfolioRequestService = portfolioRequestService;
          _userService = userService;
      }
      #endregion
  [HttpPost]
      [ValidateAntiForgeryToken]
      [HasPermissionAttribute(PermissionId.ManagePortfolioRequest)]
      public ActionResult Create(CreateViewModel viewModel)
      {
          if (ModelState.IsValid)
          {
              // validate file exists
              if (viewModel.File != null &amp;&amp; viewModel.File.ContentLength &gt; 0)
              {
                  // TODO: ggomez - also add to CreatePortfolioRequestCollection method
                  // see if file upload input control can be restricted to excel and csv
                  // add additional info below control
                  if (_portfolioRequestService.ValidatePortfolioRequestFileType(viewModel.File.FileName))
                  {
                      try
                      {
                          // create new PortfolioRequestCollection instance
                          _portfolioRequestService.CreatePortfolioRequestCollection(viewModel.File.FileName, viewModel.File.InputStream, viewModel.ReasonId, PortfolioRequestCollectionSourceId.InternalWebsiteUpload, viewModel.ReviewAllRequestsBeforeRelease, _userService.GetUserName());
                          _unitOfWork.Commit();                            
                      }
                      catch (Exception ex)
                      {
                          ModelState.AddModelError(string.Empty, ex.Message);
                          return View(viewModel);
                      }
  
                      return RedirectToAction("Index", null, null, "The portfolio construction request was successfully submitted!", null);
                  }
                  else
                  {
                      ModelState.AddModelError("File", "Only Excel and CSV formats are allowed");
                  }
              }
              else
              {
                  ModelState.AddModelError("File", "A file with portfolio construction requests is required");
              }
          }
  
  
          IEnumerable&lt;PortfolioRequestCollectionReason&gt; portfolioRequestCollectionReasons = _unitOfWork.Repository&lt;PortfolioRequestCollectionReason&gt;().Get();
          viewModel.Init(portfolioRequestCollectionReasons);
          return View(viewModel);
      }
  </code></pre>
  
  <p>On the web application I am using Unity DI container to inject the same instance of the unit of work per http request to all callers, so the controller class gets a new instance and then the service class that uses the unit of work gets the same instance as the controller. This way the service adds some records to the repository which is enrolled in a unit of work and can be committed by the client code in the controller.</p>
  
  <p>One question regarding the code and architecture described above. How can I get rid of the unit of work dependency at the service classes? Ideally I don't want the service class to have an instance of the unit of work because I don't want the service to commit the transaction, I just would like the service to have a reference to the repository it needs to work with, and let the controller (client code) commit the operation when it see fits.</p>
  
  <p>On to the windows service application, I would like to be able to get a set of records with a single unit of work, say all records in pending status. Then I would like to loop through all those records and query the database to get each one individually and then check the status for each one during each loop because the status might have changed from the time I queried all to the time I want to operate on a single one. The problem I have right now is that my current architecture doesn't allow me to have multiple unit of works for the same instance of the service.</p>
  
  <pre><code>public class ProcessPortfolioRequestsJob : JobBase
  {
      IPortfolioRequestService _portfolioRequestService;
      public ProcessPortfolioRequestsJob(IPortfolioRequestService portfolioRequestService)
      {
          _portfolioRequestService = portfolioRequestService;
      }
  </code></pre>
  
  <p>The Job class above takes a service in the constructor as a dependency and again is resolved by Unity. The service instance that gets resolved and injected depends on a unit of work. I would like to perform two get operations on the service class but because I am operating under the same instance of unit of work, I can't achieve that.</p>
  
  <p>For all of you gurus out there, do you have any suggestions on how I can re-architect my application,  unit of work + repository + service classes to achieve the goals above?</p>
  
  <p>I intended to use the unit of work + repository patterns to enable testability on my service classes, but I am open to other design patterns that will make my code maintainable and testable at the same time while keeping separation of concerns.</p>
  
  <p><strong>Update 1</strong>
  Adding the DataContext class that inheris from EF's DbContext where I declared my EF DbSets and configurations.</p>
  
  <pre><code>public class DataContext : DbContext
  {
      public DataContext()
          : base("name=ArchSample")
      {
          Database.SetInitializer&lt;DataContext&gt;(new MigrateDatabaseToLatestVersion&lt;DataContext, Configuration&gt;());
          base.Configuration.ProxyCreationEnabled = false;
      }
  
      public DbSet&lt;PortfolioRequestCollection&gt; PortfolioRequestCollections { get; set; }
  
      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
          modelBuilder.Conventions.Remove&lt;PluralizingTableNameConvention&gt;();
          modelBuilder.Configurations.Add(new PortfolioRequestCollectionConfiguration());
  
          base.OnModelCreating(modelBuilder);
      }
  }
  </code></pre>