Abp.VNext-工作单元Unitofwork

事务工作单元=数据库事务+工作单元事务。

Controller

[ApiController]
[Route("[controller]")]
public class BlogController : AbpController
{
    private BlogAppService _blogAppService => LazyServiceProvider.LazyGetRequiredService<BlogAppService>();
    public BlogController()
    {
    }

    [HttpPost("Add")]
    public async Task<IResultOutput> AddBlogAsync(AddBlogInputDto input)
    {
        return ResultOutput.Ok(await _blogAppService.AddBlogAsync1(input));
    }
}

自动工作单元

Abp默认具有的方式。

InsertAsync方法第二个参数autosave的值默认为false,代表不开启数据库事务,值为true时代表开启数据库事务。有以下几点需要注意

  1. 无论设置为false还是true,插入之后都必须等待工作单元事务提交,数据才会进入到数据库表中。例如下面代码执行完InsertAsync方法后数据是不会入库的,而是等待Controller层的AddBlogAsync方法执行完之后才会入库,即工作单元事务提交之后才会入库。
  2. 无论设置为false还是true,执行完InsertAsync方法都可以拿到blog的Id值,但是切记若设置为false,则在工作单元事务未提交前不可以根据此Id值去数据库表做查询操作,此时会报异常。除非设置为true。
  3. 无论设置为false还是true,若InsertAsync方法执行是成功的,但在工作单元事务提交前检测到其它地方存在异常,此时数据不会入库。
  4. 当值为false时,若实体属性本身赋值存在问题,例如实体某属性的值超过了数据库表对应字段指定的长度,此时执行完InsertAsync方法后不会报错,但是程序运行结束会报错,数据也不会入库;而当值为true时,程序执行InsertAsync方法便会立即报错,终止工作单元事务的提交,数据也不会入库。
public class BlogAppService : ApplicationService
 {
    public async Task<Guid> AddBlogAsync1(AddBlogInputDto inputDto)
    {
        var blog = await _blogRepository.InsertAsync(ObjectMapper.Map<AddBlogInputDto, Blog>(inputDto));
        //var blog = await _blogRepository.InsertAsync(ObjectMapper.Map<AddBlogInputDto, Blog>(inputDto),true);
        if (blog != null)
        {
            var blog1 = await _blogRepository.GetAsync(blog.Id); //autosave为false时查询会报错查不到,除非设置为true
            //do something
        }
        blog.CreationTime = _clock.Now;
        return blog.Id;
    }	
}

注意事项

  1. 在HttpGet请求方法中执行数据库操作,不会创建数据库事务。发生异常不会回滚。
public async Task<Blog> ChangeDbTestAsync()
{
    var blog = new Blog()
    {
        Name = "泰达米尔",
        ShortName = "蛮王"
    };

    //需要等待整个工作单元提交数据才会入库。
    //var entity = await _blogRepository.InsertAsync(blog); 

    //执行完此行代码数据就入库
    //var entity = await _blogRepository.InsertAsync(blog,true); 

    //执行完此行代码数据就入库,即使后面抛出异常也不会回滚
    var entity = await _blogRepository.InsertAsync(blog, true); 
    throw new Exception("模拟异常");
    return entity;
}

解决办法:在控制器层开启工作单元(应用层开启无效)

 [UnitOfWork(true, IsDisabled = false)]
 public async Task<IResultOutput> ChangeDbTestAsync()
 {
     return ResultOutput.Ok(await _blogAppService.ChangeDbTestAsync());
 }
public async Task<Blog> ChangeDbTestAsync()
{
    var blog = new Blog()
    {
        Name = "泰达米尔",
        ShortName = "蛮王"
    };

    //需要等待整个工作单元提交数据才会入库。
    //var entity = await _blogRepository.InsertAsync(blog); 

    //需要等待整个工作单元提交数据才会入库。
    //var entity = await _blogRepository.InsertAsync(blog,true);


    //需要等待整个工作单元提交数据才会入库。
    var entity = await _blogRepository.InsertAsync(blog, true); 
    throw new Exception("模拟异常");
    return entity;
}

手动工作单元

_unitOfWorkManager.Begin()方法的第二个参数isTransactional,代表是否开启工作单元事务,默认为false不开启,为true则开启,有几点注意事项

  1. Begin()的isTransactional设置为false,InsertAsync()的autosave设置为true,代表不开启工作单元事务,开启数据库事务,此时执行完InsertAsync方法后数据就会入库。
public class BlogAppService : ApplicationService
 {
    private IUnitOfWorkManager _unitOfWorkManager =>LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>();
    public async Task<Guid> AddBlogAsync1(AddBlogInputDto inputDto)
    {
        using(var uow = _unitOfWorkManager.Begin(true,false))
        {
            var blog = await _blogRepository.InsertAsync(ObjectMapper.Map<AddBlogInputDto, Blog>(inputDto), true);
            blog.CreationTime = _clock.Now;
            return blog.Id;
        }
    }	
}
  1. Begin()的isTransactional设置为true,InsertAsync()的autosave设置为true,代表既开启工作单元事务,也开启数据库事务,此时直到程序结束数据都不会入库,也不会报错。必须加上await uow.Commit()这句代码,当执行这句代码后数据便会入库。
public class BlogAppService : ApplicationService
{
    private IUnitOfWorkManager _unitOfWorkManager =>LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>();
    public async Task<Guid> AddBlogAsync1(AddBlogInputDto inputDto)
    {
        using(var uow = _unitOfWorkManager.Begin(true,true))
        {
            var blog = await _blogRepository.InsertAsync(ObjectMapper.Map<AddBlogInputDto, Blog>(inputDto), true);
            blog.CreationTime = _clock.Now;
            //await uow.Commit();  手动提交工作单元
            return blog.Id;
        }
    }	
}
  1. Begin()的isTransactional设置为false,InsertAsync()的autosave设置为false,代表既不开启工作单元事务,也不开启数据库事务,此时数据不会入库。也不会报错。但是若加上await uow.Commit()这句代码,当执行这句代码后数据便会入库(不推荐这么做)。
public class BlogAppService : ApplicationService
{
    private IUnitOfWorkManager _unitOfWorkManager =>LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>();
    public async Task<Guid> AddBlogAsync1(AddBlogInputDto inputDto)
    {
        using(var uow = _unitOfWorkManager.Begin(true,false))
        {
            var blog = await _blogRepository.InsertAsync(ObjectMapper.Map<AddBlogInputDto, Blog>(inputDto), false);
            blog.CreationTime = _clock.Now;
            //await uow.Commit();  手动提交工作单元
            return blog.Id;
        }
    }	
}
  1. Begin()的isTransactional设置为true,InsertAsync()的autosave设置为false,代表开启工作单元事务,不开启数据库事务,此时数据不会入库。也不会报错。但是若加上await uow.Commit()这句代码,当执行这句代码后数据便会入库。
public class BlogAppService : ApplicationService
{
    private IUnitOfWorkManager _unitOfWorkManager =>LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>();
    public async Task<Guid> AddBlogAsync1(AddBlogInputDto inputDto)
    {
        using(var uow = _unitOfWorkManager.Begin(true,true))
        {
            var blog = await _blogRepository.InsertAsync(ObjectMapper.Map<AddBlogInputDto, Blog>(inputDto), false);
            blog.CreationTime = _clock.Now;
            //await uow.Commit();  手动提交工作单元
            //do something
            return blog.Id;
        }
    }	
}
posted @   相遇就是有缘  阅读(133)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
  1. 1 我记得 赵雷
  2. 2 北京东路的日子 汪源
  3. 3 把回忆拼好给你 王贰浪
北京东路的日子 - 汪源
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

Not available

点击右上角即可分享
微信分享提示