2020年4月18日 星期六

[MVC/Pattern] Unit of Work與Repository模式紀錄

前言:
上一次用到Unif Of Work,已經快3年了,有機會就來記錄一下吧。

先上個圖:


Repository部分讓商業邏輯跟資料存取可以拆開,也是一種pattern,
IRepository定義了常用的CRUD操作,使用泛型處理不同的資料實體,
建立Repository instance時,注入搭配的UnitOfWork instance。

而Unit Of Work負責處理資料交易的部分,確保資料與db是一致的。
當然,多了這些抽象,寫測試也就水到渠成了。

實際程式碼如下:
public interface IUnitOfWork : IDisposable
{ 

	DbContext DbContext { get; set; }
    
	void Commit();

}

public class UnitOfWork : IUnitOfWork
{

        public DbContext DbContext { get; set; }

        public UnitOfWork()
        {
            DbContext = new ApplicationDbContext();
        }

        public void Commit()
        {
            DbContext.SaveChanges();
        }

        public void Dispose()
        {
            DbContext.Dispose();
        }
        
}

public interface IRepository<T> where T : class
{

        IUnitOfWork UnitOfWork { get; set; }

        void Create(T entity);

        IQueryable<T> ReadAll();

        IQueryable<T> Read(Expression<Func<T, bool>> filter);

        void Delete(T entity);

        void Save();

}

public class Repository<T> : IRepository<T> where T : class
{

	private DbSet _entity;
    
	public Repository(IUnitOfWork unitOfWork)
	{
	    UnitOfWork = unitOfWork;
	}

	public IUnitOfWork UnitOfWork { get; set; }

	public void Create(T entity)
        {
            Entity.Add(entity);
        }

        public IQueryable ReadAll()
        {
            return Entity;
        }

        public IQueryable Read(Expression> filter)
        {
            return Entity.Where(filter);
        }

        public void Delete(T entity);
        {
            Entity.Remove(entity);
        }

        public void Save()
        {
            UnitOfWork.Commit();
        }

}


參考資料:
https://docs.microsoft.com/zh-tw/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
https://web.csulb.edu/~pnguyen/cecs475/pdf/repository%20pattern.pdf