
本章我們繼續IUnitOfWork的開發,從之前的IRepository接口中就可以看出,我們並沒有處理單元事務,
數據CUD每次都是立即執行的,這樣有一些不好的地方,比如數據訪問次數會增多,一筆數據的完整性無法保證
比如:批量新增2條記錄,只有一條成功,這樣的情況就應該Rollback;可能有人已經想到用數據庫自帶的事務保證完整性
雖然是可以,但是這樣就不可避免地在業務層耦合SqlTransaction,我不想這種情況出現;
所以我們用windows自帶的分布式事務TransactionScope來實現,TransactionScope可以實現多個數據庫的事務鎖,這點就比SqlTransaction強一些
當然我了解到分布式事務是不一般的復雜的,那些更好的處理方式我還沒有掌握,所以先這么寫吧,有這方面經驗的朋友歡迎提建議
IUnitOfWork.cs
1 public interface IUnitOfWork<T> where T : class 2 { 3 void RegisterAdd(T entity, Action callback); 4 void RegisterUpdate(T entity, Action callback); 5 void RegisterDelete(T entity, Action callback); 6 void Commit(); 7 }
注冊新增操作:RegisterAdd
注冊更新操作:RegisterUpdate
注冊修改操作:RegisterDelete
提交數據:Commit
工作單元的實現
1 public class UnitOfWork<T> : IUnitOfWork<T> where T : class 2 { 3 private Dictionary<T, Action> addEntities; 4 private Dictionary<T, Action> updateEntities; 5 private Dictionary<T, Action> deleteEntities; 6 7 public UnitOfWork() 8 { 9 addEntities = new Dictionary<T, Action>(); 10 updateEntities = new Dictionary<T, Action>(); 11 deleteEntities = new Dictionary<T, Action>(); 12 } 13 14 public void RegisterAdd(T entity, Action callback) 15 { 16 this.addEntities.Add(entity, callback); 17 } 18 19 public void RegisterUpdate(T entity, Action callback) 20 { 21 this.updateEntities.Add(entity, callback); 22 } 23 24 public void RegisterDelete(T entity, Action callback) 25 { 26 this.deleteEntities.Add(entity, callback); 27 } 28 29 public void Commit() 30 { 31 using (TransactionScope scope = new TransactionScope()) 32 { 33 foreach (var entity in deleteEntities.Keys) 34 { 35 this.deleteEntities[entity](); 36 } 37 38 foreach (var entity in updateEntities.Keys) 39 { 40 this.updateEntities[entity](); 41 } 42 43 foreach (var entity in addEntities.Keys) 44 { 45 this.addEntities[entity](); 46 } 47 48 scope.Complete(); 49 } 50 } 51 }
這里我們用了Action,這個是無返回值委托方法,如果大家需要返回值可以用Func
實現我們還是用DapperRepository,修改一下。在新增方法中注冊數據持久化方法

好了,現在我們來看看測試結果
測試工作單元

還是用原來那個DapperRepositoryTest
我們修改一下實現過程:
單個新增

批量新增

運行結果

我們把表結構改一下,名稱改成不能為null

AddBatch也要修改,正常的執行結果一個是拋出異常
1 [TestMethod] 2 public void AddBatch() 3 { 4 try 5 { 6 var loginUser1 = new LoginUser() 7 { 8 Id = Guid.NewGuid(), 9 LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(), 10 Password = "mima1987", 11 IsEnabled = 1, 12 CreateTime = DateTime.Now 13 }; 14 15 var loginUser2 = new LoginUser() 16 { 17 Id = Guid.NewGuid(), 18 //LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(), 19 Password = "mima1987", 20 IsEnabled = 1, 21 CreateTime = DateTime.Now 22 }; 23 24 var list = new List<LoginUser>(); 25 list.Add(loginUser1); 26 list.Add(loginUser2); 27 28 repository.AddBatch(list); 29 unitOfWork.Commit(); 30 } 31 catch (Exception ex) 32 { 33 var err = ex.Message; 34 } 35 36 //long count = repository.Count(t => t.LoginName.In(new string[] { loginUser1.LoginName, loginUser2.LoginName })); 37 38 //Assert.AreEqual(true, count >0); 39 }
運行看看

如期運行,到這里,工作單元就講完了
完整項目架構
我們來看看完整的數據訪問層架構

整個數據訪問層就講完了,雖然有些簡陋,但是基本功能都有了
項目架構開發系列
- 項目架構開發:數據訪問層之Cache
- 項目架構開發:數據訪問層之Logger
- 項目架構開發:數據訪問層之Query
- 項目架構開發:數據訪問層之Repository
- 項目架構開發:數據訪問層之UnitOfWork
