工作单元模式/IUnitOfWorK/DbContext

UOW学前预习

使用该功能需要对仓储方法有一定了解,工作单元其实是快捷调用仓储方法

学习仓储:https://www.donet5.com/Home/Doc?typeId=1228

工作单元优势

 超级简单事务使用支持跨方法和多库

 超级简单的换库

 超级简单的使用仓储

手动创建工作单元

1.有泛型

 //db用SqlSugarScope模式支持跨方法事务
 using (var uow = db.CreateContext<MyDbContext>())//;默认带事务 CreateContext<MyDbContext>(IsTran=true)
  {
        //uow.变量.仓储方法
        uow.Orders.Insert(new OrderInfo() { Id = 1, Name = "order1", Price = 100 });
        uow.OrderItem.Insert(new OrderItem() { OrderId = 1, Price=100 });
        //使用原生对象
        uow.Orders.AsQueryable().ToList();
        uow.Orders.AsUpdateable(new OrderInfo() { }).ExecuteCommand();
        //使用Db
        uow.Db.Queryable<OrderInfo>().ToList();
        uow.Db.MasterQueryable<OrderInfo>().ToList();//读写分离查询走主库
        //也可以手动调用仓储
        //var orderItemDal=uow.GetMyRepository<DbSet<OrderItem>>();
        
        //这行不能少
        uow.Commit();//使用事务一定要记得写提交
  }
  
  /// <summary>
   /// 自定义DbContext
  /// </summary>
  public class MyDbContext : SugarUnitOfWork
  {
       public DbSet<OrderItem> OrderItem { get; set; }
       public DbSet<OrderInfo> Orders { get; set; }
  }
  
  /// <summary>
  /// 自定义仓储
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public class DbSet<T> : SimpleClient<T> where T : class, new()
  { 
       //可以重写仓储方法
       //可以添加新方法
  }

2.无泛型

直接用比较简单些,可以方便的调用仓储方法

using(var context = db.CreateContext())//;默认带事务 CreateContext(IsTran=true)
{
 
  //使用Orm自带仓储 
  var ds=context.GetRepository<Order>();
  ds.Insert(list);
 
  //使用自定义仓储
  var ds2 = context.GetMyRepository<Repository<Order>>();
  ds2 .Insert(list);
  
  //也可以直接用db
  context.Db.Queryable<Order>().ToList();
  
  //这行不能少
  context.Commit();//使用事务一定要记得写提交
 
 }

接口说明(5.1.3.46-preview08

 //可以用无SqlSugar接口接收 ,有些用户想通用接口中不能有SqlSugar对象
 public interface ISugarUnitOfWorkClear
 {
        RepositoryType GetMyRepository<RepositoryType>() where RepositoryType : new();

        bool Commit();
 }
 // ISugarUnitOfWork 继承 ISugarUnitOfWorkClear
  public interface ISugarUnitOfWork : ISugarUnitOfWorkClear
  {
        ISqlSugarClient Db { get;  }
        ITenant Tenant { get;  }

        SimpleClient<T> GetRepository<T>() where T : class, new();
  }

IOC注入工作单元

1.有泛型

注入工作单元 (如果用的SqlSuagr.Ioc看上面手动创建)

//创建一个注入类
public static class SqlsugarSetup
{
    public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration,
    string dbName = "db_master")
    {
         //多租户 new SqlSugarScope(List<ConnectionConfig>,db=>{});
         
        SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
        {
            DbType = SqlSugar.DbType.MySql,
            ConnectionString = configuration.GetConnectionString(dbName),
            IsAutoCloseConnection = true,
        },
         db =>{  /***写AOP等方法***/});
        ISugarUnitOfWork<MyDbContext> context = new SugarUnitOfWork<MyDbContext>(sqlSugar);
        services.AddSingleton<ISugarUnitOfWork<MyDbContext>>(context);
    }
}

//注入SqlSugar到API
services.AddSqlsugarSetup(Configuration);



/// <summary>
/// 自定义DbContext
/// </summary>
public class MyDbContext : SugarUnitOfWork
{
  public DbSet<OrderItem> OrderItem { get; set; }
  public DbSet<OrderInfo> Orders { get; set; }
}
   
/// <summary>
/// 自定义仓储
/// </summary>
/// <typeparam name="T"></typeparam>
public class DbSet<T> : SimpleClient<T> where T : class, new()
{ 
   //可以重写仓储方法
   //可以添加新方法
}

使用工作单元

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    ISugarUnitOfWork<MyDbContext> Context;
    //ISqlSugarClient db;
    public WeatherForecastController(ISugarUnitOfWork<MyDbContext> Context)
    {
        this.Context = Context;
        //也可以拿到Db
        //db = Context.Db;
    }

    [HttpGet]
    public bool Get()
    {
        using (var uow = Context.CreateContext()) //;默认带事务 CreateContext(IsTran=true)
        {
           uow.Orders.Insert(new OrderInfo() { Id = 1, Name = "order1", Price = 100 });
           uow.Orders.Insert(new OrderInfo() { Id = 2, Name = "order2", Price = 200 });
            
           //使用原生对象
           //uow.Orders.AsQueryable().ToList(); 
           //使用Db 
           //uow.Db.Queryable<Order>().ToList();
           return uow.Commit();//使用带事务记得写提交
        }
       
    }
}

2.无泛型

 SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
        {
            DbType = SqlSugar.DbType.MySql,
            ConnectionString = configuration.GetConnectionString(dbName),
            IsAutoCloseConnection = true,
        },
         db =>{  /***写AOP等方法***/});;
 services.AddSingleton<ISqlSugarClient>(sqlSugar);

 public class ApiService()
 {
     ISqlSugarClinet _db;
     public ApiService(ISqlSugarClinet db)
     {
       _db=db;
     }
     
      public void Test()
      {
         using(var uow=_db.CreateContext())  
         {
             var ds=uow.GetRepository<Order>();
             ds.Insert(list);
   
             uow.Commit();//使用事务一定要记得写提交
         }    
      }
 }

 

工作单元自动换库

1.有泛型

在工作单元内会根据特性自动切换数据库(注意:如果一个实体对应多个库那么这种情部不适合工作单元,看文档SAAS分库)

 //多库配置
  //具体用法看文档多租户这里详的介绍配置多库
 new ConnectionConfig(){ConfigId="0",DbType=DbType.SqlServer,ConnectionString="..",IsAutoCloseConnection=true},
 new ConnectionConfig(){ConfigId="1",DbType=DbType.MySql, ConnectionString="...",IsAutoCloseConnection=true}
 
 //实体配置
 [Tenant("1")] //匹配ConfigId
 public class OrderInfo
 {
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
 }

2.无泛型

需要用自定义仓储才支持自动换库

var ds2 = context.GetMyRepository<Repository<Order>>();
ds2.Insert(list);

仓储多库用法: https://www.donet5.com/Home/Doc?typeId=2405


事务嵌套

    //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会自动回滚
     }


特性实现工作单元

在 Furion 框架中完美支持SqlSugar工作单元特性,我们只需要在控制器 Action 中贴 [UnitOfWork] 特性即可开启工作单元模式,保证了每一次请求都是一个 工作单元,要么同时成功,要么同时失败。 

[UnitOfWork]    // 由于出现错误,所以所有数据库变更都会自动回滚
public async Task 测试环境事务(int id)
{
    // 各种奇葩数据库操作
    await _personRepository.DeleteNowAsync(id);
    // 其他数据库操作。。
    // 故意出错
    var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");
}

下载DEMO:

 

SqlSugarTran.zip


文档:SqlSugar5.0