Abp之工作單元與事務


 

環境:Abp1.2

疑問:沒有調用工作單元的SaveChanges方法引起的事務提交時機的問題.

例如:有一個應用服務代碼如下:

 public void CreatePhrase(PhraseCreateDto input)
        {var phrase = Mapper.Map<Phrase>(input);
                phrase.Id = Guid.NewGuid();
                _phraseRepository.Insert(phrase); 
        }

根據用戶提交數據插入一條記錄,但在方法末未顯式調用SaveChanges方法

在Mvc的Controller里調用上述方法的代碼如下:

   [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方法,每次就能獲得最新的記錄數:

        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方法並不會提交事務,所以拋出異常后,外層的工作單元就會回滾事務.

不過Begin有幾個重載,例如:

Required:默認值,如果事務不存在則新建,如果已存在,則用之.

RequiresNew:始終新建事務.所以如果使用:var uow=UnitOfWorkManager.Begin(TransactionScopeOption.RequiresNew),則在拋出異常前提交事務.

Suppress:抑制外界的事務,工作單元域內的所有操作會被提交.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM