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时代表开启数据库事务。有以下几点需要注意
- 无论设置为false还是true,插入之后都必须等待工作单元事务提交,数据才会进入到数据库表中。例如下面代码执行完InsertAsync方法后数据是不会入库的,而是等待Controller层的AddBlogAsync方法执行完之后才会入库,即工作单元事务提交之后才会入库。
- 无论设置为false还是true,执行完InsertAsync方法都可以拿到blog的Id值,但是切记若设置为false,则在工作单元事务未提交前不可以根据此Id值去数据库表做查询操作,此时会报异常。除非设置为true。
- 无论设置为false还是true,若InsertAsync方法执行是成功的,但在工作单元事务提交前检测到其它地方存在异常,此时数据不会入库。
- 当值为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;
}
}
注意事项
- 在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则开启,有几点注意事项
- 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;
}
}
}
- 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;
}
}
}
- 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;
}
}
}
- 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;
}
}
}
人生如逆旅
我亦是行人

浙公网安备 33010602011771号