title: How can I implement a transaction for my repositories with Entity Framework?
body: <p>I am trying to utilize the repository design pattern in my application for 2 reasons</p>
  
  <ol>
  <li><p>I like to de-couple my application from Entity in case I decide to not use Entity Framework at some point</p></li>
  <li><p>I want to be able reuse the logic that interacts with the model</p></li>
  </ol>
  
  <p>I successfully setup and used the repository pattern. However, I have one complexity to deal with which is a transaction.</p>
  
  <p>I want to be able to use transaction so that I can make multiple calls to the repository and then commit or rollback.</p>
  
  <p>Here is my repository interface</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq.Expressions;
  
  namespace Support.Repositories.Contracts
  {
      public interface IRepository&lt;TModel&gt; where TModel : class
      {
          // Get records by it's primary key
          TModel Get(int id);
  
          // Get all records
          IEnumerable&lt;TModel&gt; GetAll();
  
          // Get all records matching a lambda expression
          IEnumerable&lt;TModel&gt; Find(Expression&lt;Func&lt;TModel, bool&gt;&gt; predicate);
  
          // Get the a single matching record or null
          TModel SingleOrDefault(Expression&lt;Func&lt;TModel, bool&gt;&gt; predicate);
  
          // Add single record
          void Add(TModel entity);
  
          // Add multiple records
          void AddRange(IEnumerable&lt;TModel&gt; entities);
  
          // Remove records
          void Remove(TModel entity);
  
          // remove multiple records
          void RemoveRange(IEnumerable&lt;TModel&gt; entities);
      }
  }
  </code></pre>
  
  <p>Then I create an implementation for Entity Framework like so</p>
  
  <pre><code>using Support.Repositories.Contracts;
  using System;
  using System.Collections.Generic;
  using System.Data.Entity;
  using System.Linq;
  using System.Linq.Expressions;
  
  namespace Support.Repositories
  {
      public class EntityRepository&lt;TEntity&gt; : IRepository&lt;TEntity&gt;
          where TEntity : class
      {
          protected readonly DbContext Context;
          protected readonly DbSet&lt;TEntity&gt; DbSet;
  
          public EntityRepository(DbContext context)
          {
              Context = context;
              DbSet = context.Set&lt;TEntity&gt;();
          }
  
          public TEntity Get(int id)
          {
              return DbSet.Find(id);
          }
  
          public IEnumerable&lt;TEntity&gt; GetAll()
          {
              return DbSet.ToList();
          }
  
          public IEnumerable&lt;TEntity&gt; Find(Expression&lt;Func&lt;TEntity, bool&gt;&gt; predicate)
          {
              return DbSet.Where(predicate);
          }
  
          public TEntity SingleOrDefault(Expression&lt;Func&lt;TEntity, bool&gt;&gt; predicate)
          {
              return DbSet.SingleOrDefault(predicate);
          }
  
          public void Add(TEntity entity)
          {
              DbSet.Add(entity);
          }
  
          public void AddRange(IEnumerable&lt;TEntity&gt; entities)
          {
              DbSet.AddRange(entities);
          }
  
          public void Remove(TEntity entity)
          {
              DbSet.Remove(entity);
          }
  
          public void RemoveRange(IEnumerable&lt;TEntity&gt; entities)
          {
              DbSet.RemoveRange(entities);
          }
  
      }
  }
  </code></pre>
  
  <p>Now, I create a <code>IUnitOfWork</code> to interact with repository like so</p>
  
  <pre><code>using System;
  
  namespace App.Repositories.Contracts
  {
      public interface IUnitOfWork : IDisposable
      {
          IUserRepository Users { get; }
          IAddressRepository Addresses { get;  }
      }
  }
  </code></pre>
  
  <p>Then I implemented this interface for Entity Framework like this:</p>
  
  <pre><code>using App.Contexts;
  using App.Repositories.Contracts;
  using App.Repositories.Entity;
  
  namespace App.Repositories
  {
      public class UnitOfWork : IUnitOfWork
      {
          private readonly AppContext _context;
          public IUserRepository  Users { get; private set; }
          public IAddressRepository Addresses { get; private set; }
  
          public UnitOfWork(AppContext context)
          {
              _context = context;
  
              Users = new UserRepository(_context);
              Addresses = new AddressRepository(_context);
          }
  
          public UnitOfWork() : this(new AppContext())
          {
          }
  
          public int Save()
          {
              return _context.SaveChanges();
          }
  
          public void Dispose()
          {
              _context.Dispose();
          }
      }
  }
  </code></pre>
  
  <p>I am able to use the repository like this</p>
  
  <pre><code>using(var repository = new UnitOfWork())
  {
       repository.Users.Add(new User(... User One ...))
       repository.Save();
  
       repository.Addresses(new Address(... Address For User One ...))
       repository.Save();
  
       repository.Users.Add(new User(... User Two...))
       repository.Save();
  
       repository.Addresses(new Address(... Address For User Two...))
       repository.Save();
  }
  </code></pre>
  
  <p>Now, I want to be able to use database transaction so only when everything is good then commit otherwise rollback.</p>
  
  <p>My first take is to add a new method called <code>BeginTransaction()</code> to my <code>UnitOfWork</code> class. But will couple my code to Entity Framework only.</p>
  
  <p>Now, I am thinking to create a new interface that provides <code>BeginTransaction()</code>, <code>Commit()</code> and <code>Rollback()</code> method which will allow me to write an implementation for any ORM.</p>
  
  <p>i.e.</p>
  
  <pre><code>namespace Support.Contracts
  {
      public IRepositoryDatabase
      {
          SomethingToReturn BeginTransaction();
  
          void Commit();
          void Rollback();
      }
  }
  </code></pre>
  
  <p>The question is how would I tie <code>IRepositoryDatabase</code> back to my UnitOfWork so I can implement correctly? And what would <code>BeginTransaction()</code> needs to return?</p>