How can I implement a transaction for my repositories with Entity Framework?
<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>