title: Repository Pattern with Entity Framework 4.1 and Parent/Child Relationships
body: <p>I still have some confusion with the Repository Pattern. The primary reason why I want to use this pattern is to avoid calling EF 4.1 specific data access operations from the domain. I'd rather call generic CRUD operations from a IRepository interface. This will make testing easier and if I ever have to change the data access framework in the future, I will be able to do so without refactoring a lot of code.</p>
  
  <p>Here is an example of my situation:</p>
  
  <p>I have 3 tables in the database: <code>Group</code>, <code>Person</code>, and <code>GroupPersonMap</code>. <code>GroupPersonMap</code> is a link table and just consists of the <code>Group</code> and <code>Person</code> primary keys. I created an EF model of the 3 tables with VS 2010 designer. EF was smart enough to assume <code>GroupPersonMap</code> is a link table so it doesn't show it in the designer. I want to use my existing domain objects instead of EF's generated classes so I turn off code generation for the model. </p>
  
  <p>My existing classes that matches the EF model are as follows:</p>
  
  <pre><code>public class Group
  {
     public int GroupId { get; set; }
     public string Name { get; set; }
  
     public virtual ICollection&lt;Person&gt; People { get; set; }
  }
  
  public class Person
  {
     public int PersonId {get; set; }
     public string FirstName { get; set; }
  
     public virtual ICollection&lt;Group&gt; Groups { get; set; }
  }
  </code></pre>
  
  <p>I have a generic repository interface like so:</p>
  
  <pre><code>public interface IRepository&lt;T&gt; where T: class
  {
      IQueryable&lt;T&gt; GetAll();
      T Add(T entity);
      T Update(T entity);
      void Delete(T entity);
      void Save()
  }
  </code></pre>
  
  <p>and a generic EF repository:</p>
  
  <pre><code>public class EF4Repository&lt;T&gt; : IRepository&lt;T&gt; where T: class
  {
      public DbContext Context { get; private set; }
      private DbSet&lt;T&gt; _dbSet;
  
      public EF4Repository(string connectionString)
      {
          Context = new DbContext(connectionString);
          _dbSet = Context.Set&lt;T&gt;();
      }
  
      public EF4Repository(DbContext context)
      {
          Context = context;
          _dbSet = Context.Set&lt;T&gt;();
      }
  
      public IQueryable&lt;T&gt; GetAll()
      {
          // code
      }
  
      public T Insert(T entity)
      {
          // code
      }
  
      public T Update(T entity)
      {
          Context.Entry(entity).State = System.Data.EntityState.Modified;
          Context.SaveChanges();
      }
  
      public void Delete(T entity)
      {
          // code
      }
  
      public void Save()
      {
          // code
      }
  }
  </code></pre>
  
  <p>Now suppose I just want to map an existing <code>Group</code> to an existing <code>Person</code>. I would have to do something like the following:</p>
  
  <pre><code>        EFRepository&lt;Group&gt; groupRepository = new EFRepository&lt;Group&gt;("name=connString");
          EFRepository&lt;Person&gt; personRepository = new EFRepository&lt;Person&gt;("name=connString");
  
          var group = groupRepository.GetAll().Where(g =&gt; g.GroupId == 5).First();
          var person = personRepository.GetAll().Where(p =&gt; p.PersonId == 2).First();
  
          group.People.Add(person);
          groupRepository.Update(group);
  </code></pre>
  
  <p>But this doesn't work because EF thinks <code>Person</code> is new, and will try to re-<code>INSERT</code> the <code>Person</code> into the database which will cause a primary key constraint error. I must use <code>DbSet</code>'s <code>Attach</code> method to tell EF that the <code>Person</code> already exists in the database so just create a map between <code>Group</code> and <code>Person</code> in the <code>GroupPersonMap</code> table.</p>
  
  <p>So in order to attach <code>Person</code> to the context I must now add an <code>Attach</code> method to my IRepository:</p>
  
  <pre><code>public interface IRepository&lt;T&gt; where T: class
  {
      // existing methods
      T Attach(T entity);
  }
  </code></pre>
  
  <p>To fix the primary key constraint error:</p>
  
  <pre><code>EFRepository&lt;Group&gt; groupRepository = new EFRepository&lt;Group&gt;("name=connString");
  EFRepository&lt;Person&gt; personRepository = new EFRepository&lt;Person&gt;(groupRepository.Context);
  
  var group = groupRepository.GetAll().Where(g =&gt; g.GroupId == 5).First();
  var person = personRepository.GetAll().Where(p =&gt; p.PersonId == 2).First();
  
  personRepository.Attach(person);
  group.People.Add(person);
  groupRepository.Update(group);
  </code></pre>
  
  <p>Fixed. Now I have to deal with another issue where <code>Group</code> is being UPDATE'd in the database every time I create a Group/Person map. This is because in my <code>EFRepository.Update()</code> method, the entity state is explicitly set to <code>Modified'. I must set the Group's state to</code>Unchanged<code>so the</code>Group` table doesn't get modified.</p>
  
  <p>To fix this I must add some sort of <code>Update</code> overload to my IRepository that does not update the root entity, or <code>Group</code>, in this case:</p>
  
  <pre><code>public interface IRepository&lt;T&gt; where T: class
  {
      // existing methods
      T Update(T entity, bool updateRootEntity);
  }
  </code></pre>
  
  <p>The EF4 implentation of the Update method would look something like this:</p>
  
  <pre><code>T Update(T entity, bool updateRootEntity)
  {
     if (updateRootEntity)
        Context.Entry(entity).State = System.Data.EntityState.Modified;
     else
        Context.Entry(entity).State = System.Data.EntityState.Unchanged;
  
      Context.SaveChanges();
  }
  </code></pre>
  
  <p>My question is: Am I approaching this the right way? My Repository is starting to look EF centric as I start to work with EF and the repository pattern. Thanks for reading this long post</p>