To start with lets us take up the two most important questions, “What” and “Why

What is Repository Pattern?

Repository pattern is basically a layer to separate the Data access logic, thus avoiding duplication of Data Access Logic.
It has direct access to Database, ORM etc.
The repository behaves like a collection of data to which we can add, delete and update objects.

Why use Repository Pattern?

Let us take the example of an MVC application with Entity Framework, now in case of a basic application, we use database context directly inside our controllers, but this creates a tight coupling between controller and data access layer, and it also violates the SOLID principle, where it does not obey Single Responsibility Principle.
Now in cases, we make changes to Data access layer, the controller code can break.
To avoid all this hassle, we need to include one more layer, in between MVC controller and SQL Server Database, that is Repository.

To implement this pattern, we can use the approach of having a one-repository per model, which means, each entity of the database will have its own repository.

Let us create a basic Interface first

public interface IRepository<T> where T: class
{
    IEnumerable<T> GetAll(Func<T, bool> predicate = null);
    T Get(Func<T, bool> predicate);
    void Add(T entity);
    void Delete(T entity);
}

Now using this interface we can create specific repositories for specific tables.

public class StudentsRepository : IRepository<Student>
{
private DbEntities entities = new DbEntities();

public IEnumerable<Student> GetAll(Func<Student, bool> predicate = null)
{
    if (predicate != null)
    {
        return entities.Students.Where(predicate);
    }
    return entities.Students;
}

public Student Get(Func<Student, bool> predicate)
{
    return entities.Students.FirstOrDefault(predicate);
}

public void Add(Student entity)
{
    entities.Students.AddObject(entity);
}

public void Delete(Student entity)
{
    entities.Students.DeleteObject(entity);
}

internal void SaveChanges()
{
    entities.SaveChanges();
}
}

Hence we can create an instance of this StudentsRepository in the controller to get data.
Now let us imagine a scenario where we have many tables, so to manage them we will have many repositories and each repository will have its own Context Object, but if we look carefully, each repository having its own initializations to the database is wrong. Hence comes the concept of Unit Of Work.

So let us create a separate Repository and pass Context Object from outside via Unit Of Work.

public class StudentsRepositoryWithUow : IRepository<Student>
{
private DbEntities entities = null;

public StudentsRepositoryWithUow(DbEntities _entities)
{
    entities = _entities;
}

    //Data Manipulation functions      
}


public class UnitOfWork : IDisposable
{
private DbEntities entities = null;
public UnitOfWork()
{
    entities = new DbEntities();
}

IRepository<Student> studentRepository = null;

public IRepository<Student> StudentRepository
{
    get
    {
        if (studentRepository == null)
        {
            studentRepository = new StudentRepositoryWithUow(entities);
        }
        return studentRepository;
    }
}
    //Other Repository Initializations

public void Dispose():base()
{
   GC.SuppressFinalize(this);
}
}

Hence the Controller can be initialized as

public class StudentUowController : Controller
{
private UnitOfWork uow = null; 
//
// GET: /Students/

public StudentUowController()
{
    uow = new UnitOfWork();
}

public StudentUowController(UnitOfWork uow_)
{
    this.uow = uow_;
}
    //Actions
}

Now if we rewrite all the repositories, only one Context Object is created throughout the application. By this we have achieved, centralized code for accessing data, maintaining all the laws of SOLID Principle.