数据库异步并发执行

适用场景

需要满足下面2条 

1、 你想要最快的执行完,并且不在乎短期占用太多资源,能保证线程安全(比Task.Run 性能更快,也不需要考虑线程安全)

2、 数据库操作10个以上,如果只有几个数据库操作就没必要用了和一般的异步没多少区别

注意:每种数据库用法不一样 


1、支持所有库写法

Task并行执行数量在100以下为佳,如果超过100需要设置max pool size=1000,

并且建议并行执行一次不要超1000 (如果是SqlServer用法2性能更好)

 var ts = new List<Task>();
 for (int i = 0; i < 1000; i++)//建议一次执行Task不工
 {
    //需要CopyNew()强制new出新对象,因为AsyncLocal没办法区分异步上下文
     ts.Add(db.CopyNew().Queryable<Order>().FirstAsync());
  }
  await Task.WhenAll(ts);
//如果用db.CopyNew().XXX.ToListAsync()这种不需要包Task.Run


//db.ThenMapper异步并发需要这样处理
 var ts = new List<Task>();
 for (int i = 0; i < 1000; i++)//建议一次执行Task不工
 {
   var newDb=db.CopyNew();
   var list=await newDb.Queryable....;
   ts.Add(newDb.ThenMapperAsync...)
  }
  await Task.WhenAll(ts);

2、SqlServer | Sqlite | Oracle

注意:1、异步方法   Task.WhenAll

          2、db是同一个,并且用事务

          3、SqlServer需要连接字符串加上 MultipleActiveResultSets=True  

          4、Thenmapper 要按标题1来实现


下面是一个完整的用例并且测试通过

using System.Linq;
using System.Threading.Tasks;

namespace OrmTest
{
    class Program
    {
        static async Task Main(string[] args)

        {

            int max = 1000;

            Task[] tasks = new Task[max];

            var db = GetClient();//db需要是同一个
            db.BeginTran(); //强制关闭自动释放(如果手动释放可以不用事务)
            

            for (int i = 0; i < max; i++)

            {
      

               //如果是SqlSugarScope禁止出现Task.Run 
               //原因:有Task.Run SqlSugarScope异步上下文会变事务会有问题 
                tasks[i]=db.Queryable<Order>()
                       .Take(10)
                        .ToListAsync();//直接等于ORM异步方法

            }

            await Task.WhenAll(tasks);
            db.CommitTran(); //关闭数据库
        }

        private static SqlSugarClient GetClient()  //SqlSugarClient和SqlSugarScope都行
        {
            return new SqlSugarClient(new ConnectionConfig()
            {
                DbType = SqlSugar.DbType.SqlServer, //SqlServer Sqlite Oracle
                //注意配置
                ConnectionString = OrmTest.Config.ConnectionString,
                IsAutoCloseConnection = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuting = (sql, p) =>
                    {
                        Console.WriteLine(sql);
                        Console.WriteLine(string.Join(",", p?.
                        Select(it => it.ParameterName + ":" + it.Value)));
                    }
                }
            });
        }
    }
}


测试结果

本身IIS就是多线程操作,所以不是特殊需求没必要并发查询,并发查询会把数据库的IO充份利用,并且可以保证线程安全,

配置 1165G7 SSD  结果

Task.WhenAll

1000个1秒   
Task.Run(()=>{ var db=new  sqlsugarclient(); db.xxx})1000就10秒 




关闭
果糖网