title: Using DDD and AutoMapper, how do you do work on the same aggregate root in multiple services within a single unit of work?
body: <p>I am trying to learn and implement domain driven design in a non-web based project.  I have a main loop that will do multiple procedures on a lot of entities in a single unit of work.  I don't want any of the changes to be persisted unless the entire loop's work is successful.  I'm using AutoMapper to convert persistence models to domain models within a repository, and my services are using the repository to retrieve data before doing work.</p>
  
  <p>There are some elements of DDD that are not working well with my project and I am hoping someone can tell me what I have wrong about the whole process.  </p>
  
  <p>Here are the DDD ideas I'm struggling with:</p>
  
  <ul>
  <li>Domain services should be used when a process involves multiple aggregate roots interacting with each other</li>
  <li>You should pass aggregate root Ids into domain services which will then use repositories to load them</li>
  <li>Repositories should return domain models that it constructs from mapped persistence models (in this case I am using AutoMapper)</li>
  </ul>
  
  <p>Here is an example of what I'm trying to do.</p>
  
  <pre><code>using (var scope = serviceProvider.CreateScope())
              {
                  var unitOfWork = scope.ServiceProvider.GetService&lt;IUnitOfWork&gt;();
                  var aggregate1Repo = scope.ServiceProvider.GetService&lt;IAggregate1Repository&gt;();
                  var aggregate2Repo = scope.ServiceProvider.GetService&lt;IAggregate2Repository&gt;();
                  var aggregate3Repo = scope.ServiceProvider.GetService&lt;IAggregate3Repository&gt;();
                  var firstService = scope.ServiceProvider.GetService&lt;IFirstService&gt;();
                  var secondService = scope.ServiceProvider.GetService&lt;ISecondService&gt;();
  
                  var aggregate1 = aggregate1Repo.Find(1); //First copy of aggregate1
                  var aggregate2 = aggregate2Repo.Find(1000); 
                  var aggregate3 = aggregate3Repo.Find(123); 
  
                  aggregate1.DoSomeInternalWork();
  
                  firstService.DoWork(aggregate1.Id,aggregate2.Id); 
                  secondService.DoWork(aggregate1.Id,aggregate3.Id);
  
                  aggregate1Repo.Update(aggregate1);
                  unitOfWork.Commit();
              }
  </code></pre>
  
  <p>Aggregate1Repo:</p>
  
  <pre><code>public class Aggregate1Repository
  {
      private readonly AppDBContext _dbContext;
      private IMapper _mapper;
  
      public Aggregate1Repository(AppDBContext context, IMapper mapper)
      {
          _dbContext = context;
          _mapper = mapper;
      }   
  
      public Aggregate1 Find(int id)
      {
          return _mapper.Map&lt;Aggregate1&gt;(_dbContext
              .SomeDBSet.AsNoTracking()
              .Find(id));
      }
  }
  </code></pre>
  
  <p>FirstService:</p>
  
  <pre><code>public class FirstService : IFirstService
  {
      private readonly IAggregate1Repository _agg1Repo;
      private readonly IAggregate2Repository _agg2Repo;
  
      public FirstService(IAggregate1Repository agg1Repo, IAggregate2Repository agg2Repo)
      {
          _agg1Repo = agg1Repo;
          _agg2Repo = agg2Repo;
      }
  
      public void DoWork(int aggregate1Id, int aggregate2Id)
      {
          var aggregate1 = _agg1Repo.Find(aggregate1Id); //second copy of aggregate1
          var aggregate2 = _agg2Repo.Find(aggregate2Id);
          //do some calculations and modify aggregate1 in some fashion
          //I could update aggregate1 in the repository here,
          // but this copy of aggregate1 doesn't have the changes made prior to this point
      }
  }
  </code></pre>
  
  <p>SecondService:</p>
  
  <pre><code>public class SecondService : ISecondService
  {
      private readonly IAggregate1Repository _agg1Repo;
      private readonly IAggregate3Repository _agg3Repo;
  
      public FirstService(IAggregate1Repository agg1Repo, IAggregate3Repository agg3Repo)
      {
          _agg1Repo = agg1Repo;
          _agg3Repo = agg3Repo;
      }
  
      public void DoWork(int aggregate1Id, int aggregate3Id)
      {
          var aggregate1 = _agg1Repo.Find(aggregate1Id); //third copy of aggregate1
          var aggregate3 = _agg2Repo.Find(aggregate3Id);
          //do some calculations and modify aggregate1 in some fashion
          //I could update aggregate1 in the repository here,
          // but this copy of aggregate1 doesn't have the changes made prior to this point
      }
  }
  </code></pre>
  
  <p>The problem here is that I'd essentially be doing work to three different copies of aggregate1 since a new object is created by AutoMapper in the repository each time I try to load it.  I could put separate calls to aggregate1Repo.Update in the two services, but I'd still be working on three different objects that all represent the same thing.  I feel like I must have a fundamental flaw in my thinking, but I don't know what it is.</p>