SmartSql使用教程(3)——SmartSql中的事务,及AOP的使用
一、引言
经过两章的铺垫,我们现在对SmartSql已经有了一定的了解,那么今天我们的主题是事务处理。事务处理是常用的一种特性,而SmartSql至少提供了两种使用事务的方法。一种是通过Repository(动态仓储)或者ITransaction的常规调用,一种是基于AOP提醒的动态代理方式。接下来我们一个个说。
上图是这一章的项目结构,这次的结构略微有点复杂,我一一解释。
项目结构分为3个部分,Api部分分成了3个.NetCore MVC项目,三个项目分别是常规调用;基于.NetCore原生DI的AOP调用;基于Autofac的AOP调用,AOP部分的区别只是在DI的配置部分。
DomainService也就是业务逻辑层,这个没什么好说的。
Data Access部分是实体与动态仓储,而在这一章中。我们的动态仓储项目有一个小的变动。先放图
通过图片可以看到,原来我们放在Api项目中的Map和Config都放到了动态仓储的项目。这个因为在当前项目中,我们有3个输出项目。如果每个项目中都写一套Maps就显得很多此一举。所以把它们统一的放到仓储类库里来,是一个很好的办法(虎哥提供)。注:别忘记把文件设置成始终复制哦
二、 常规使用
用法写在上面忽略了的DomainService中
using System;
using SmartSql.DbSession;
using SmartSqlSampleChapterThree.Entity;
using SmartSqlSampleChapterThree.Repository; namespace SmartSqlSampleChapterThree.DomainService
{
public class NormalUserDomainService : IUserDomainService
{
private const string DEFAULT_AVATAR = "https://smartsql.net/logo.png"; private readonly IUserRepository _userRepository;
private readonly IUserDetailRepository _userDetailRepository;
private readonly ITransaction _transaction; public NormalUserDomainService(IUserRepository userRepository, IUserDetailRepository userDetailRepository, ITransaction transaction)
{
_userRepository = userRepository;
_userDetailRepository = userDetailRepository;
_transaction = transaction;
} public User Register(string loginName, string password, string nickname)
{
try
{
_transaction.BeginTransaction();
var user = new User
{
LoginName = loginName,
Password = password,
Status = ,
CreateTime = DateTime.Now,
ModifiedTime = DateTime.Now
}; user.Id = _userRepository.Insert(user); _userDetailRepository.Insert(new UserDetail
{
UserId = user.Id,
Nickname = nickname,
Avatar = DEFAULT_AVATAR,
Sex = null,
CreateTime = DateTime.Now,
ModifiedTime = DateTime.Now
}); _transaction.CommitTransaction();
return user;
}
catch
{
_transaction.RollbackTransaction();
throw;
}
} // use transaction on repository's sql mapper
public User RegisterUseRepository(string loginName, string password, string nickname)
{
try
{
_userRepository.SqlMapper.BeginTransaction(); var user = new User
{
LoginName = loginName,
Password = password,
Status = ,
CreateTime = DateTime.Now,
ModifiedTime = DateTime.Now
}; user.Id = _userRepository.Insert(user); _userDetailRepository.Insert(new UserDetail
{
UserId = user.Id,
Nickname = nickname,
Avatar = DEFAULT_AVATAR,
Sex = null,
CreateTime = DateTime.Now,
ModifiedTime = DateTime.Now
}); _userRepository.SqlMapper.CommitTransaction();
return user;
}
catch
{
_userRepository.SqlMapper.RollbackTransaction();
throw;
}
}
}
}
NormalUserDomainService
在这个类中,我实现了两次事务调用。在第一个方法中我们使用ITransaction接口提供的方法,调用了Begin-Commit-Rollback的事务过程。
第二个方法中,我直接使用了Repository.SqlMap.BeginTransaction(),这是因为IRepository包含了一个ISqlMap,而ISqlMap同时继承了ITransaction。所以本质上这两种方式是等价的。
三、AOP
1. Nuget依赖
SmartSql有一个独立的Nuget包来支持AOP实现。名字就叫“SmartSql.AOP”
2. DomainService
使用了AOP后,我们的业务代码就可以干净很多。只需要在方法前加上[Transaction]特性就可以了。只要方法体中抛出异常,事务即会回滚。另外需要注意的地方是,AOP方法是需要用上virtual虚方法标识的。
[Transaction]
public virtual User Register(string loginName, string password, string nickname)
{
var user = new User { LoginName = loginName, Password = password, Status = , CreateTime = DateTime.Now, ModifiedTime = DateTime.Now };
user.Id = _userRepository.Insert(user);
_userDetailRepository.Insert(new UserDetail { UserId = user.Id, Nickname = nickname, Avatar = DEFAULT_AVATAR, Sex = null, CreateTime = DateTime.Now, ModifiedTime = DateTime.Now });
return user;
}
3. 原生配置
在Startup中稍稍修改一下ConfigureServices即可。
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc(); /// 服务注册 Begin /// 服务注册 End return services.BuildAspectInjectorProvider();
}
看一下上面代码你会发现,只需要为ConfigureServices方法加一个IServiceProvider返回值。并在方法最后加一句return就可以了。
4. Autofac配置
在Autofac中与原生相比,略微有一些不同。
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc(); /// 服务注册 Begin /// 服务注册 End // autofac
var builder = new ContainerBuilder(); builder.RegisterDynamicProxy(config =>
{
config.Interceptors
.AddTyped<TransactionAttribute>(Predicates.ForNameSpace("SmartSqlSampleChapterThree.DomainService"));
});
builder.Populate(services); var container = builder.Build();
return new AutofacServiceProvider(container);
}
我在项目中很少使用Autofac,所以对它的特性也不是很了解。只是按照文档做了最简单的实现,这里还要特别感谢交流群的小伙伴(QQ群号:604762592)。是群里的一个小伙伴在使用Autofac的时候分享了他的使用方式。
这里在原生的基础上,创建一个Autofac容器构建器,并在构建器中注册一个动态代理。然后在拦截器中加上TransactionAttribute就可以了。
三、结语
以上就是SmartSql中事务处理的一些方法,希望可以帮助到你。
下期预告:TypeHandler类型处理器使用讲解 And 如何自定义TypeHandler
SmartSql使用教程(3)——SmartSql中的事务,及AOP的使用的更多相关文章
- SmartSql使用教程(2)——使用动态代理实现CURD
一.引言 接着上一篇的教程,本章我们继续讲SmartSql.今天的主题是动态仓储. 老规矩,先上一个项目结构 从第二章开始.我们将原来的单一项目做了一个分离.方便之后的更新. 在这个结构中.原本上一章 ...
- SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务
一.引言 最近SmartSql被正式引入到了NCC,借着这个契机写一个使用教程系列 二.SmartSql简介[摘自官方文档] 1. SmartSql是什么? SmartSql = MyBatis + ...
- Entity Framework入门教程(19)---EF中使用事务
EF中使用事务 这节介绍EF6中事务的使用.EF core中事务的使用方式和EF6中一模一样. 1.EF中的默认的事务 默认情况下,当我们执行一个SaveChanges()方法时就会新建了一个事务,然 ...
- SQL Server中的事务日志管理(9/9):监控事务日志
当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...
- Spring中@Transactional事务回滚
转载: Spring中@Transactional事务回滚 一.使用场景举例 在了解@Transactional怎么用之前我们必须要先知道@Transactional有什么用.下面举个栗子:比如一个部 ...
- 【MySQL】我这样分析MySQL中的事务,面试官对我刮目相看!!
写在前面 相信大部分小伙伴在面试过程中,只会针对面试官提出的表面问题来进行回答.其实不然,面试官问的每一个问题都是经过深思熟虑的,面试的时间相对来说也是短暂的,面试官不可能在很短的时间内就对你非常了解 ...
- Microsoft SQL Server中的事务与并发详解
本篇索引: 1.事务 2.锁定和阻塞 3.隔离级别 4.死锁 一.事务 1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一 ...
- Redis系列之key操作命令与Redis中的事务详解(六)
序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...
- SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...
随机推荐
- SVG 签名动画 制作
不知道哪天看到的一个朋友圈里面有发的什么什么免费教签名之类的,就看了下SVG,做这功能还不错. 主要用到的几个属性,需要自行百度一下,不详说 stroke-dashoffset , stroke- ...
- Linux随笔记
Linux配置apt-get源地址 以Ubuntu配置网易开源镜像站为例: 访问地址:http://mirrors.163.com/,找到对应的系统. 先将source.list进行备份,执行: su ...
- h5的复制功能
js+html5实现复制文字按钮 <div> <input type="text" name="guanfangaddress" id=&qu ...
- MySQL Infobright 数据仓库快速安装笔记[转]
[文章作者:张宴 本文版本:v1.1 最后修改:2010.05.18 转载请注明原文链接:http://blog.zyan.cc/infobright/] Infobright是一个与MySQL集成的 ...
- 多线程(C++)临界区Critical Sections
一 .Critical Sections(功能与Mutex相同,保证某一时刻只有一个线程能够访问共享资源,但是不是内核对象,所以访问速度比Mutex快,但是没有等待超时的功能,所以有可能导致死锁,使用 ...
- EasyDarwin添加自定义的服务模块EasyMyModule
EasyDarwin模块的要求 每个QTSS模块必须实现两个方法函数: 一个Main入口函数,服务器在启动的时候将调用这个方法函数,来对您开发的模块所在的QTSS stub库进行初始化. 一个Disp ...
- c/c++标准库中的文件操作总结
1 stdio.h是c标准库中的标准输入输出库 2 在c++中调用的方法 直接调用即可,但是最好在函数名前面加上::,以示区分类的内部函数和c标准库函数. 3 c标准输入输出库的使用 3.1 核心结构 ...
- Git简介和安装
一.什么是Git? Git是一个分布式版本控制系统,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来.如图所示: 任何一处的服务器或者个人机发生故障,都可以用其它机器的任何一个镜像出来 ...
- 【C++基础学习】成员对象与对象数组
第一部分 对象成员与对象数组 从一个简单的例子开始说起,首先定义一个Coordinate的类,里面有两个公有的成员变量m_iX和m_iY,分别代表横坐标和纵坐标. 接下来,定义一个对象数组cood和一 ...
- Windows下配置PHPUnit(pear已弃用,使用phpunit.phar)
一.配置PHPUnit 首先到PHPUnit官网(点此进入)下载相应的版本.php 5.5及以下版本请使用PHPUnit 4.8.得到 .phar 文件,并把名字改为 phpunit.phar . 把 ...