一、引言

  经过两章的铺垫,我们现在对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的使用的更多相关文章

  1. SmartSql使用教程(2)——使用动态代理实现CURD

    一.引言 接着上一篇的教程,本章我们继续讲SmartSql.今天的主题是动态仓储. 老规矩,先上一个项目结构 从第二章开始.我们将原来的单一项目做了一个分离.方便之后的更新. 在这个结构中.原本上一章 ...

  2. SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务

    一.引言 最近SmartSql被正式引入到了NCC,借着这个契机写一个使用教程系列 二.SmartSql简介[摘自官方文档] 1. SmartSql是什么? SmartSql = MyBatis + ...

  3. Entity Framework入门教程(19)---EF中使用事务

    EF中使用事务 这节介绍EF6中事务的使用.EF core中事务的使用方式和EF6中一模一样. 1.EF中的默认的事务 默认情况下,当我们执行一个SaveChanges()方法时就会新建了一个事务,然 ...

  4. SQL Server中的事务日志管理(9/9):监控事务日志

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

  5. Spring中@Transactional事务回滚

    转载: Spring中@Transactional事务回滚 一.使用场景举例 在了解@Transactional怎么用之前我们必须要先知道@Transactional有什么用.下面举个栗子:比如一个部 ...

  6. 【MySQL】我这样分析MySQL中的事务,面试官对我刮目相看!!

    写在前面 相信大部分小伙伴在面试过程中,只会针对面试官提出的表面问题来进行回答.其实不然,面试官问的每一个问题都是经过深思熟虑的,面试的时间相对来说也是短暂的,面试官不可能在很短的时间内就对你非常了解 ...

  7. Microsoft SQL Server中的事务与并发详解

    本篇索引: 1.事务 2.锁定和阻塞 3.隔离级别 4.死锁 一.事务 1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一 ...

  8. Redis系列之key操作命令与Redis中的事务详解(六)

    序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...

  9. SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

随机推荐

  1. angular 复选框checkBox多选的应用

    应用场景是这样的,后台返回的数据在页面上复选框的形式repeat出来 可能会有两种需求: 第一:后台返回的只有项,而没有默认选中状态(全是待选状态) 这种情况相对简单只要repeat出相应选项 第二: ...

  2. 字符串转换成js的日期格式

    js字符串转日期格式 ,JavaScript字符串转日期格式 大家都知道JS是根据结果来确定数据类型的. 当然我们也是可以转化的,下面我就介绍两种关于JS字符串类型转换成日期类型的方法, 我个人比较喜 ...

  3. wordpress系列1:安装

    https://wordpress.org/download/release-archive/ 官方中文网站:https://cn.wordpress.org/ readme.html文件,可查看Wo ...

  4. poj 1730Perfect Pth Powers(分解质因数)

                                                             id=1730">Perfect Pth Powers Time Li ...

  5. C#特性类的使用

    特性类的使用过程: 第一步:定义一个特性类,定义一些成员来包含验证时需要的数据:第二步:创建特性类实例:创建一个特性类的实例,里面包含着验证某一个属性或者字段需要的数据.将该实例关联到某个属性上面.第 ...

  6. React深入源码--了解Redux用法之Provider

    在Redux中最核心的自然是组件,以及组件相关的事件与数据流方式.但是我们在Redux中并没有采用传统的方式在getInitialState()中去初始化数据,而是采用Provider统一处理,省去了 ...

  7. mongodb学习之:安全和认证

    mongodb默认是不认证的,默认没有账号,只要能连接上服务就可以对数据库进行各种操作,mongodb认为安全最好的方法就是在一个可信的环境中运行它,保证之后可信的机器才能访问它.因此需要在登录的时候 ...

  8. NSString和NSMutableNSString的基本用法

    // // main.m // NSString /** NSString 1.NSString 是一个不可以变的字符串对象 2.NSMutableString是一个可变字符串. 下面代码为字符串的: ...

  9. jquery特效(3)—轮播图①(手动点击轮播)

    写了一个轮播图练练手,先写了一个手动点击轮播的轮播图,随后我会慢慢接着深入写自动轮播图和鼠标悬浮图片停止移动轮播图等,虽然今天我生日,但是代码还是得写的,不能找借口放松自己,原地踏步也算后退. 下面来 ...

  10. 一看就会,科目三靠边停车30cm技巧!再也不怕不会停车了!

    靠边停车是科目三考试的最后一关,如果在这一关失败,那之前所有的努力都功亏一篑了,你感觉吃不吃亏?就连我们自己平时开车,轮胎万一与路边石阶刮蹭,就会造成不小的伤害.那么靠边停车时有哪些注意要点呢?请和小 ...