Abp.VNext-工作单元Unitofwork
1.Abp.VNext-发布自定义领域事件2.Abp.VNext-拆分查询3.Abp.VNext-统一配置UTC时区时间4.Abp.VNext-显示/延迟加载5.Abp.VNext-显示加载实体导航属性6.Abp.VNext-数据过滤7.Abp.VNext-懒加载LazyServiceProvider8.Abp.VNext-异步执行帮助类AsyncHelper9.Abp.VNext-异步执行器AsyncExecuter10.Abp.VNext-聚合根类11.Abp.VNext-数据审计12.Abp.VNext-SaveChanges事务提交
13.Abp.VNext-工作单元Unitofwork
14.Abp.VNext-模块事务工作单元=数据库事务+工作单元事务。
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;
}
}
}
人生如逆旅
我亦是行人
合集:
Abp.VNext 知识点集锦
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?