title: Repository pattern and mapping between domain models and Entity Framework
body: <p>My repositories deal with and provide persistence for a rich domain model.  I do not want to expose the anemic, Entity Framework data entity to my business layers, so I need some way of mapping between them.</p>
  
  <p>In most cases, constructing a domain model instance from a data entity requires the use of parameterised constructors and methods (since it is rich).  It is not as simple as a property/field match.  AutoMapper could be used for the opposite situation (mapping to data entities) but not when creating domain models.</p>
  
  <p><strong>Below is the core of my repository pattern.</strong>  </p>
  
  <p>The <code>EntityFrameworkRepository</code> class works with two generic types:</p>
  
  <ul>
  <li><code>TDomainModel</code>: The rich domain model</li>
  <li><code>TEntityModel</code>: The Entity Framework data entity</li>
  </ul>
  
  <p>Two abstract methods are defined: </p>
  
  <ul>
  <li><code>ToDataEntity(TDomainModel)</code>: To convert to data entities (for <code>Add()</code> and <code>Update()</code> methods)</li>
  <li><code>ToDomainModel(TEntityModel)</code>: To construct domain models (for the <code>Find()</code> method).  </li>
  </ul>
  
  <p>Concrete implementations of these methods would define the mapping required for the repository in question.</p>
  
  <pre><code>public interface IRepository&lt;T&gt; where T : DomainModel
  {
      T Find(int id);
      void Add(T item);
      void Update(T item);
  }
  
  public abstract class EntityFrameworkRepository&lt;TDomainModel, TEntityModel&gt; : IRepository&lt;TDomainModel&gt;
      where TDomainModel : DomainModel
      where TEntityModel : EntityModel
  {
      public EntityFrameworkRepository(IUnitOfWork unitOfWork)
      {
          // ...
      }
  
      public virtual TDomainModel Find(int id)
      {
          var entity = context.Set&lt;TEntityModel&gt;().Find(id);
  
          return ToDomainModel(entity);
      }
  
      public virtual void Add(TDomainModel item)
      {
          context.Set&lt;TEntityModel&gt;().Add(ToDataEntity(item));
      }
  
      public virtual void Update(TDomainModel item)
      {
          var entity = ToDataEntity(item);
  
          DbEntityEntry dbEntityEntry = context.Entry&lt;TEntityModel&gt;(entity);
  
          if (dbEntityEntry.State == EntityState.Detached)
          {
              context.Set&lt;TEntityModel&gt;().Attach(entity);
  
              dbEntityEntry.State = EntityState.Modified;
          }
      }
  
      protected abstract TEntityModel ToDataEntity(TDomainModel domainModel);
      protected abstract TDomainModel ToDomainModel(TEntityModel dataEntity);
  }
  </code></pre>
  
  <p><strong>Here is a basic example of a repository implementation:</strong></p>
  
  <pre><code>public interface ICompanyRepository : IRepository&lt;Company&gt;
  {
      // Any specific methods could be included here
  }
  
  public class CompanyRepository : EntityFrameworkRepository&lt;Company, CompanyTableEntity&gt;, ICompanyRepository
  {
      protected CompanyTableEntity ToDataEntity(Company domainModel)
      {
          return new CompanyTable()
          {
              Name = domainModel.Name,
              City = domainModel.City
              IsActive = domainModel.IsActive
          };
      }
  
      protected Company ToDomainModel(CompanyTableEntity dataEntity) 
      {
          return new Company(dataEntity.Name, dataEntity.IsActive)
          {
              City = dataEntity.City
          }
      }
  }
  </code></pre>
  
  <p><strong>Problem:</strong></p>
  
  <p>A <code>Company</code> might be composed of many <code>Departments</code>.  If I want to eagerly load these from the <code>CompanyRepository</code> when fetching a <code>Company</code> then where would I define the mapping between a <code>Department</code> and a <code>DepartmentDataEntity</code>?</p>
  
  <p>I could provide more mapping methods in the <code>CompanyRepository</code>, but this will soon get messy.  There would soon be duplicated mapping methods across the system.</p>
  
  <p>What is a better approach to the above problem?</p>