Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework and Unit of Work

I am using EF/Repository/Unit of Work, but I am having a hard time understanding some details. Inside the UnitOfWork, I create a new EF DbContext (EmmaContext), but look at inside the repository, I cast it which I know is wrong, how do I get the context inside the repo correctly? Maybe I am totally on the wrong path?

Here is my UnitOfWork:

//Interface
public interface IUnitOfWork : IDisposable
{
    void Commit();
}

//Implementation
public class UnitOfWork : IUnitOfWork
{
    #region Fields/Properties
    private bool isDisposed = false;
    public EmmaContext Context { get; set; }
    #endregion

    #region Constructor(s)
    public UnitOfWork()
    {
        this.Context = new EmmaContext();
    }
    #endregion

    #region Methods
    public void Commit()
    {
        this.Context.SaveChanges();
    }

    public void Dispose()
    {
        if (!isDisposed)
            Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        isDisposed = true;
        if (disposing)
        {
            if (this.Context != null)
                this.Context.Dispose();
        }
    }
    #endregion
}

Here is the repository:

//Interface
public interface IRepository<TEntity> where TEntity : class
{
    IQueryable<TEntity> Query();
    void Add(TEntity entity);
    void Attach(TEntity entity);
    void Delete(TEntity entity);
    void Save(TEntity entity);
}

//Implementation
public abstract class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
    #region Fields/Properties
    protected EmmaContext context;
    protected DbSet<TEntity> dbSet;
    #endregion

    #region Constructor(s)
    public RepositoryBase(IUnitOfWork unitOfWork)
    {
        this.context = ((UnitOfWork)unitOfWork).Context;
        this.dbSet = context.Set<TEntity>();
    }
    #endregion

    #region Methods
    public void Add(TEntity entity)
    {
        dbSet.Add(entity);
    }

    public void Attach(TEntity entity)
    {
        dbSet.Attach(entity);
    }

    public void Delete(TEntity entity)
    {
        dbSet.Remove(entity);
    }

    public IQueryable<TEntity> Query()
    {
        return dbSet.AsQueryable();
    }

    public void Save(TEntity entity)
    {
        Attach(entity);
        context.MarkModified(entity);
    }
    #endregion
}
like image 267
Sam Avatar asked Aug 28 '12 20:08

Sam


2 Answers

Sam: I usually feel comfortable with a concrete Repository taking a concrete UnitOfWork in the ctor:

   public RepositoryBase(UnitOfWork unitOfWork)
   {
        this.context = unitOfWork.Context;
        this.dbSet = context.Set<TEntity>();
   }

The repository and UoW typically work in concert and need to know a little bit about each other.

Of course the code consuming these classes only know about the interface definitions and not the concrete types.

like image 63
OdeToCode Avatar answered Oct 30 '22 21:10

OdeToCode


This is the best article I've read.

In their example, they manage the repositories like this:

    private SchoolContext context = new SchoolContext();
    private GenericRepository<Department> departmentRepository;
    private GenericRepository<Course> courseRepository;

    public GenericRepository<Department> DepartmentRepository
    {
        get
        {

            if (this.departmentRepository == null)
            {
                this.departmentRepository = new GenericRepository<Department>(context);
            }
            return departmentRepository;
        }
    }

Your unit of work holds the context, and if it needs to reference a repository, it creates it if it has not been created, and passes in the context that it's holding.

The article also walks through how they converted a regular MVC controller implementation into using the unit of work pattern.

like image 32
Mark Oreta Avatar answered Oct 30 '22 21:10

Mark Oreta