環境:Abp1.2app
疑問:沒有調用工做單元的SaveChanges方法引發的事務提交時機的問題.ui
例如:有一個應用服務代碼以下:spa
public void CreatePhrase(PhraseCreateDto input) {var phrase = Mapper.Map<Phrase>(input); phrase.Id = Guid.NewGuid(); _phraseRepository.Insert(phrase); }
根據用戶提交數據插入一條記錄,但在方法末未顯式調用SaveChanges方法code
在Mvc的Controller裏調用上述方法的代碼以下:orm
[AbpAuthorize] public ActionResult Create() { ViewBag.Count = _phraseAppService.GetCount(); return View(); } [AbpAuthorize] [HttpPost] [ValidateInput(false)] public ActionResult Create(FormCollection fc) { CheckModelState(); if ((fc.Get("editorValue") != null) && (fc.Get("ChineseMean") != null)) { //ueditor有時會在最後多出一個br換行,須要去掉. var sentenceHtml = fc.Get("editorValue"); var phrase = new PhraseCreateDto { ChineseMean = fc.Get("ChineseMean"), SentenceHtml = sentenceHtml, //1.去掉Html標籤 2.把單引號,雙引號等被轉義的字符轉回來. Sentence = Server.HtmlDecode(Common.ReplaceHtmlMark(sentenceHtml)) }; _phraseAppService.CreatePhrase(phrase); } return Create(); }
在_phraseAppService.CreatePhrase(phrase),插入記錄以後,再調用無參的Create方法,在Create方法裏ViewBag.Count = _phraseAppService.GetCount()獲得的記錄數,仍然是原來的記錄數(並無+1),也就是說插入數據發生在獲取記錄數以後,若是在CreatePhrase方法末顯式調用當前工做單元的SaveChanges方法,每次就能得到最新的記錄數:blog
public void CreatePhrase(PhraseCreateDto input) {var phrase = Mapper.Map<Phrase>(input); phrase.Id = Guid.NewGuid(); _phraseRepository.Insert(phrase); CurrentUnitOfWork.SaveChanges(); }
還有一點須要注意:工做單元與事務這兩者的關係,假若有以下代碼:事務
public void CreatePhrase(PhraseCreateDto input) { using (var uow=UnitOfWorkManager.Begin()) { var phrase = Mapper.Map<Phrase>(input); phrase.Id = Guid.NewGuid(); _phraseRepository.Insert(phrase); uow.Complete(); } throw new Exception($"the exception inner {nameof(CreatePhrase)}"); }
在調用UnitOfWorkHanle的Complete以後,拋出一個異常,那麼有沒有插入數據呢?答案是不必定,由於在應用服務方法裏默認的就是一個工做單元,再在方法裏面建一個更小範圍的工做單元,並不必定會建立一個事務,而有可能使用已經有的事務,而已有的事務歸外層的工做單元管理,因此調用Complete方法並不會提交事務,因此拋出異常後,外層的工做單元就會回滾事務.input
不過Begin有幾個重載,例如:it
Required:默認值,若是事務不存在則新建,若是已存在,則用之.io
RequiresNew:始終新建事務.因此若是使用:var uow=UnitOfWorkManager.Begin(TransactionScopeOption.RequiresNew),則在拋出異常前提交事務.
Suppress:抑制外界的事務,工做單元域內的全部操做會被提交.