回顧
上一篇我們根據工作單元的原理基於ADO.NET進行了簡單的實現,但是當項目需求發生變化的時候,比如需要引入ORM框架又要兼容當前ADO.NET實現的方式時,先前的實現就無法滿足這個需求了。
話就不多說了,我們就跟據當前的需求變化來重構工作單元吧。
重構UnitOfWork
首先我們看看原先實現的工作單元提取出來的接口,代碼如下:
public interface IUnitOfWork { void RegisterAdd(string sql, params IDataParameter[] parameters); void RegisterSave(string sql, params IDataParameter[] parameters); void RegisterRemove(string sql, params IDataParameter[] parameters); void Comit(); }
由於需求需要兼容ORM和ADO.NET方式,而以上的接口僅僅支持ADO.NET的方式,因此接口需要改變,例如:
//其他代碼省略 void RegisterAdd(object entity);
觀察以上的修改會發現如果要滿足需求,則需要判斷是ADO.NET或者是ORM的操作,那么就有了兩種不同的職責,這顯然是不合理的,但是如果我們將ADO.NET和ORM還是讓對應的數據層類去實現的話,就符合單一責任了,於是經過以上分析,就可以對以上的接口做進一步的修改了,大致代碼如下:
//其他代碼省略 void RegisterAdd(object entity, IUnitOfWorkRepository repository);
按照這個思路的話,這個IUnitOfWorkRepository的方法數量則會跟IUnitOfWork基本相同(沒有Commit),一個是注冊,而另一個則是實際的操作,因此接口代碼則會跟第一次改為object的相同了,代碼如下:
public interface IUnitOfWorkRepository { void ExecuteAdd(object entity); void ExecuteSave(object entity); void ExecuteRemove(object entity); }
有了以上的改變之后,就可以實現IUnitOfWork了,代碼結構上還是跟SQLUnitOfWork類似的,差別是原先是使用一個List<SQLEntity>來存儲所有的CUD操作,但是現在必須要區分出不同類型的操作,因此需要有分別存儲CUD的容器,大致代碼如下:
public class UnitOfWork : IUnitOfWork { private Dictionary<object, IUnitOfWorkRepository> m_addList = new Dictionary<object, IUnitOfWorkRepository>(); private Dictionary<object, IUnitOfWorkRepository> m_saveList = new Dictionary<object, IUnitOfWorkRepository>(); private Dictionary<object, IUnitOfWorkRepository> m_removeList = new Dictionary<object, IUnitOfWorkRepository>(); public void RegisterAdd(object entity, IUnitOfWorkRepository repository) { if (!this.m_addList.ContainsKey(entity)) this.m_addList.Add(entity, repository); } public void RegisterSave(object entity, IUnitOfWorkRepository repository) { if (!this.m_saveList.ContainsKey(entity)) this.m_saveList.Add(entity, repository); } public void RegisterRemove(object entity, IUnitOfWorkRepository repository) { if (!this.m_removeList.ContainsKey(entity)) this.m_removeList.Add(entity, repository); } public void Commit() { using (TransactionScope trans = new TransactionScope()) { foreach (var entity in this.m_addList.Keys) { this.m_addList[entity].ExecuteAdd(entity); } foreach (var entity in this.m_saveList.Keys) { this.m_saveList[entity].ExecuteSave(entity); } foreach (var entity in this.m_removeList.Keys) { this.m_removeList[entity].ExecuteRemove(entity); } trans.Complete(); } } }
到這里我們就將工作單元重構工作完成了,接下來就可以根據IUnitOfWorkRepository派生出基於ADO.NET和ORM的實現了。
重構SchoolRepository
首先我們先看一下重構后的代碼:
class SchoolRepository : IRepository, IUnitOfWorkRepository { private IDbConnection m_connection = null; private IUnitOfWork m_uow = null; public SchoolRepository(IDbConnection connection, IUnitOfWork uow) { this.m_connection = connection; this.m_uow = uow; } public void Add(object entity) { this.m_uow.RegisterAdd(entity, this); } public void Save(object entity) { this.m_uow.RegisterSave(entity, this); } public void Remove(object entity) { this.m_uow.RegisterRemove(entity, this); } public void ExecuteAdd(object entity) { School school = entity as School; using (IDbCommand cmd = this.m_connection.CreateCommand()) { cmd.CommandType = CommandType.Text; cmd.CommandText = "insert school values(@id, @name)"; cmd.Parameters.Add(new SqlParameter("@id", school.Id)); cmd.Parameters.Add(new SqlParameter("@name", school.Name)); cmd.ExecuteNonQuery(); } } public void ExecuteSave(object entity) { //代碼略 } public void ExecuteRemove(object entity) { //代碼略 } }
IRepository是數據層的基礎接口,從代碼中我們看到原先CUD的方法被拆分到了CUD和ExecuteXXX方法中去了,CUD方法負責調用IUnitOfWork的接口,而ExecuteXXX則實現具體的數據庫操作
基於NHibernate的IUnitOfWorkRepository實現
先看代碼吧
class SchoolRepository : IRepository, IUnitOfWorkRepository { private IUnitOfWork m_uow = null; public SchoolRepository(IDbConnection connection, IUnitOfWork uow) { this.m_uow = uow; } public void Add(object entity) { this.m_uow.RegisterAdd(entity, this); } public void Save(object entity) { this.m_uow.RegisterSave(entity, this); } public void Remove(object entity) { this.m_uow.RegisterRemove(entity, this); } public void ExecuteAdd(object entity) { SessionFactory.CurrentSession.Add(entity); } public void ExecuteSave(object entity) { //代碼略 } public void ExecuteRemove(object entity) { //代碼略 } }
從基於NHibernate的實現中,我們可以看到ExecuteXXX的方法都是去調用NHibernateSession的相關方法的。
結尾
到此數據層就只差查詢了,下次會分享一下關於查詢的模式。
文章到這里就結束了,如果有什么問題和錯誤歡迎留言,謝謝!