首页 > 代码库 > Abp之工作单元与事务

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:无需周围事务上下文,工作单元域内的所有操作会被提交.

 

Abp之工作单元与事务