单库事务是针一个db操作执行的事务,无论是 ISqlSugarClient和 SqlSugarClient 用法都一样
try
{
db.Ado.BeginTran();
db.Insertable(new Order() { .....}).ExecuteCommand();
db.Insertable(new Order() { .....}).ExecuteCommand();
db.Ado.CommitTran();
}
catch (Exception ex)
{
db.Ado.RollbackTran();
throw ex;
}如果一个db就一个库,那么你也可以用多租户事务节约代码,因为2者在一个库的情况下作用一样
db.BeginTran();//去掉了.ado db.CommitTran();//去掉了.ado db.RollbackTran();//去掉了.ado //ISqlSugarClient 接口使用多租户事务 看文档2.2
多数据库事务是SqlSugar独有的功能,稳定比CAP更强(CAP还有一层队列),在单个程序中可以很愉快的使用多库事务
SqlSugarClient或者SqlSugarSope 继承于2个接口 ,代码如下事物
SqlSugarClient : ISqlSugarClient, ITenant
多租户声明
SqlSugarClient db = new SqlSugarClient(new List<ConnectionConfig>()
{
new ConnectionConfig()
{ ConfigId="0", DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection=true},
new ConnectionConfig()
{ ConfigId="1", DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection=true}
});简单的说多租户事务和单库事务用法基本100%一致,唯一区别就是少了.Ado
db.Ado.BeginTran//单库 db.BeginTran //多库事务 db.AsTenant().BeginTran()//多库事务 一般是接口ISqlSugarClient使用
因为继承 ITenant 了可以直接使用 (老版本var mysql=db.GetConnection要写在事务外面)
//禁止使用 db.Ado.BeginTran,多租户是db.BeginTran
try
{
db.BeginTran();
db.GetConnection("1").Insertable(new Order() { }).ExecuteCommand();
db.GetConnection("0").Insertable(new Order() { }).ExecuteCommand();
db.CommitTran();
}
catch (Exception)
{
db.RollbackTran();//数据回滚
throw;
}
//主db
//注入的SqlSugarClient或者SqlSugarScope我们称为主db
//子db
//通过租户方法GetConnection出来的我们称为子db,用来操作当前数据库,没有租户事务相关方法
//主db可以用事务管理多个子db ,也可以使用 GetConnection等租户方法
//目前底层是业务执行成功后统一提交事务,业务只要失败全部回滚,统一回滚过程中都有有3次重试回滚
//从目前用户使用情况来看,相当稳定几乎没有一例失败的反馈
//高安全级别数据:请使用差异日志+Catch(AggregateException ex)进行补偿机质
//如果回滚失败会throw new AggregateException因为和ITenant没有继承关需要转换一下
db.AsTenant().BeginTran();//低版本 (db as ITenant).BeginTran() db.AsTenant().CommitTran(); db.AsTenant().RollbackTran();
db.ContextId要从事务开始,CURD 和事务结束 必须一致 这个事务才会生效,如果是MYSQL也检查一下表引擎是否支持事务
不一致怎么办?
SqlsugarClient 可以用变量 var db=外部Db; 所有操作使用db保证一致
SqlsuagrScope (该对象是线程安全对象,可以单例)可以用单例模式保证一致

测试代码 最好用 Insert ,因为Update有条件过滤等因素添会添加测试难度,我们用插入来进行测试会比较简单些
try
{
db.BeginTran();
Console.WriteLine(db.Queryable<Order>().Count());//插入前数量
db.Insertable(new Order() { CreateTime=DateTime.Now, Name="aa",Price=1}).ExecuteCommand();
Console.WriteLine(db.Queryable<Order>().Count());//插入后数量
throw new Exception("出错");
db.CommitTran();
}
catch
{
db.RollbackTran();
Console.WriteLine(db.Queryable<Order>().Count());//回滚后数量
}输出结果 插入前和回滚后一样就说明成功的

这种适合有全局异常的,直接出错扔出错并且回滚
using var tran = db.UseTran();//using不能少
db.Queryable<Order>().ToList();
db.Insertable(new Order() { Name = "a" }).ExecuteCommand();
tran.CommitTran();//commitTran提交,如果没有提交成功会自动回滚这种适合没有异常处理的,减少了try 处理
//不扔出错误
var result = db.UseTran(() =>
{
var beginCount = db.Queryable<Order>().ToList();
db.Ado.ExecuteCommand("delete Order");
var endCount = db.Queryable<Order>().Count();
return true;// 返回值等行result.Data
});
if (result.Data==false) //返回值为false
{
//result.Data 业务的返回值
//如果是上面的逻辑 result.Data==true肯定业务成功并且事务成功
//if(result.IsSuccess==false)//事务执行了回滚
//if(result.IsSuccess==true)//事务提交完成
}
//直接扔出错误
db.UseTran(() =>
{
var beginCount = db.Queryable<Order>().ToList();
db.Ado.ExecuteCommand("delete Order");
var endCount = db.Queryable<Order>().Count();
return true;
}, ex => { throw ex; });//throw exUnitOfWork: https://www.donet5.com/Home/Doc?typeId=2360
SqlSugarScope 单例模式支持跨事务方法
SqlSugarClient 需要IOC 设置 Scoped周期实现
CAP可以支持跨程序间的事务处理(非跨程序事务不建议用,涉及到队列等,在单程序中稳定性肯定不如自带的多租户事务)
注意: MySql用户使用 升级到最新
1、数据库的自动释放要关闭
2、手动打开数据库连接 db.Ado.Connection.Open();
3、用db.Ado.Connection创建事务
4、把你的事务赋值到ORM对象 db.Ado.Transaction = 你的事务;
5、执行你的代码
6、关闭Connection对象
//用户使用案例
var db=GetSqlsugarclient();
//关闭自动释放(需要 using手动释放)
db.CurrentConnectionConfig.IsAutoCloseConnection = false;
//取出ADO事务
using (var connection = (MySqlConnection)db.Ado.Connection)//SqlServer是SqlConnection
{
using (var transaction = connection.BeginTransaction(_capBus, autoCommit: false))
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
db.Ado.Transaction = (IDbTransaction)transaction.DbTransaction;//这行很重要
db.Insertable<Test>(new Test()
{
name = DateTime.Now.ToString()
}).ExecuteCommand();
_capBus.Publish("Sample.RabbitMQ.MySql", DateTime.Now);
transaction.Commit();
}
}https://github.com/DotNetNext/SqlSugar/issues/1207
备份地址
https://www.donet5.com/Ask/9/23459
请不要在同步方法里面写下面方代码,必须是异步方法才行 返回是要带有Task async
用法1:
try
{
await db.BeginTranAsync();
await db.Insertable(new Order()
{
CreateTime = DateTime.Now,
CustomId = 1,
Name = "aaa",
Price = 0
}).ExecuteCommandAsync();
await db.CommitTranAsync();
}
catch (Exception)
{
await db.RollbackTranAsync();
}用法2:
//只有5.0.3.8支持,老版本请升级使用
var res = await db.UseTranAsync(async () =>
{
await db.Insertable(new Order()
{
CreateTime = DateTime.Now,
CustomId = 1,
Name = "aaa",
Price = 0
}).ExecuteCommandAsync();
return true;//返回值会变成 res.Data
});
if (result.Data==false) //返回值为false
{
//result.Data 业务的返回值
//如果是上面的逻辑 result.Data==true肯定业务成功并且事务成功
//if(result.IsSuccess==false)//事务执行了回滚
//if(result.IsSuccess==true)//事务提交完成
}
//注意:
//await db.UseTranAsync 前面的await不要漏掉了单库模式用法
try
{
db.Ado.BeginTran(IsolationLevel.ReadCommitted);
//业务代码
db.Ado.CommitTran();
}
catch (Exception ex)
{
db.RollbackTran();
throw ex;
}多租户模式
var mysqlDb = db.GetConnection("mysql");
var mssqlDb = db.GetConnection("mssql");
try
{
mysqlDb.Ado.BeginTran(IsolationLevel.ReadCommitted);//开启库1的事务
mssqlDb.Ado.BeginTran(IsolationLevel.ReadCommitted);//开启库2的事务
//业务代码 只能用 mysqlDb和 mssqlDb
db.CommitTran();//注意不能用db.ado.CommitTran
}
catch (Exception ex)
{
db.RollbackTran();
throw ex;
}有外部事务,内部事务用外部事务(推荐)
通过工作单元实现嵌套事务 5.1.2.5-preview03
//db.Ado.IsNoTran()表示事务为null才开启事务
using (var uow = db.CreateContext(db.Ado.IsNoTran()))
{
using (var uow2 = db.CreateContext(db.Ado.IsNoTran()))
{
uow2.Commit();
}
uow.Commit(); //禁止用 db.RollBack 工作单元内只要throw会自动回滚
}不推荐原因:这种很容易出现坑,比如业务A和业务B都用到了一样的表就会死锁
try
{
db.BeginTran();
//业务..A
var childDb=db.CopyNew();
try
{
childDb.BeginTran();
//...业务B
childDb.Commit();
}
catch (Exception)
{
childDb.RollbackTran();//数据回滚
throw;
}
db.CommitTran();
}
catch (Exception)
{
db.RollbackTran();//数据回滚
throw;
}事务嵌套:推荐用9.1或者标题10 ,9.2是不推荐的
[ServiceFilter(typeof(TransactionFilter))]//加上这行就可以用了
public IEnumerable<WeatherForecast> Get()
{
.....数据库操作...
}详细用法: https://www.donet5.com/Doc/27/2537
(1)MYSQL不支持创建表和删除表处理事务,原生事务也一样
(2) MyISAM 存储引擎不支持事务 需要改成 InnoDB

2016 © donet5.comApache Licence 2.0