• 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:抑制外界的事务,工作单元域内的所有操作会被提交.

  • 相关阅读:
    [CF724G]Xor-matic Number of the Graph
    [SOJ #537]不包含 [CF102129I]Incomparable Pairs(2019-8-6考试)
    [SOJ #538]好数 [CC]FAVNUM(2019-8-6考试)
    [洛谷P4052][JSOI2007]文本生成器
    [洛谷P3966][TJOI2013]单词
    [洛谷P5158]【模板】多项式快速插值
    [洛谷P3227][HNOI2013]切糕
    【bzoj】3477: [Usaco2014 Mar]Sabotage 01分数规划
    【SPOJ
    【以前的空间】系列
  • 原文地址:https://www.cnblogs.com/kid1412/p/6352212.html
Copyright © 2020-2023  润新知