ORM增删改查并发性能测试2

前言

上一篇《ORM增删改查并发性能测试》出现了点小失误,有的输出SQL日志的代码没有禁用,数据库连接字符串可能有问题。统一环境,统一代码后,重新写一篇。

这次重点是并发性能测试,真不是为了diss其它ORM,开始是因为我写的Dapper.LiteSql高并发场景下存在BUG,才写了这个测试,经过修改优化,最好Dapper.LiteSql通过了这个测试。然后Fast.Framework的作者对它的ORM非常自信,我就好奇,是否真的有他说的这么好,口说无凭,我就对它进程各种测试,包括这个高并发测试,刚开始Fast.Framework高并发测试也不通过,后经过作者的优化,就通过了。

本测试不偏向任何ORM,有一说一。如果测试环境或程序有问题,请指出,难免有失误。

测试的现实意义

这两天在对一些ORM进行性能测试(涉及SqlSugar、FreeSql、Fast.Framework、Dapper.LiteSql),测试用的是Winform程序,别人第一眼看到我的程序,说,你这测试没意义!
可能我的测试程序的某些地方写的比较变态吧,但我认为有现实意义,并且网上有相关网站崩溃问题的文章,那什么“爆高分析”,“崩溃问题”,WinDbg用的很6,那写程序阶段为什么没发现呢?

场景

假设WebApi(或者说网站后台服务)正在被高并发访问,一段时间后,服务的线程数量达到了200正常的是类似这样的,任务来了,就干活:及以上,那么.NET的线程池,如果线程处于空闲状态,默认是20秒后释放线程,假设这200多个线程空闲了,但是还没有达到空闲20秒的时间,还没有释放,如果此时,又有大量高并发的访问,200个线程去操作数据库,那就可能很危险了。

关于性能

虽然代码写的可能有点变态,但我的测试不是很严格,也不是很规范。
性能如果不是数量级的差,问题都不大,比如一个是0.8秒,一个是1.8秒,那1.8秒的慢是慢了一点,但问题不大;但如果一个是0.8秒,一个是10秒,那10秒的这个,可能就有点问题了,即使别人用的Emit你用的反射,也不应该差这么多。
当然了,我的测试,数据规模不大,10000条,button可能会点10次,那也才10万数据量,在数据量方面我没有做极端测试,我的重点不是这个,因为很少会去查100万数据到内存中,就暂不讨论这个。
这个测试除了大体上测试一下性能,主要就是增加了并发测试。
非并发性能测试的截图我就不放全了,这几个ORM有差别,但我觉得2秒3秒还是6秒甚至8秒,都问题不大的,都算差不多,都算堪用。

测试环境

数据库及设置

测试数据库是MySQL,版本5.7.28
MySql的连接池大小是1200

ORM增删改查并发性能测试2插图

测试程序中配置的数据连接字符串

Data Source=localhost;Port=3306;User ID=root;Password=123456;Initial Catalog=xxxxxx_test;Charset=utf8mb4;SslMode=none;Allow User Variables=True;

MySql.Data.dll版本

MySql.Data.dll目前用的是最新的8.0.30版本(题外话,它里面的异步是假异步,把同步方法包装成的异步,我说怎么反而慢了呢,真异步要使用MySqlConnector.dll,Fast.Framework使用的是这个性能很好)。

参数化

测试的增删改查,都是参数化的。

实体类

以SqlSugar的为例吧,几种ORM测试用的表结构是相同的。

using System;
using System.Linq;
using System.Text;
using SqlSugar;

namespace Models
{
    ///
    ///用户表
    ///
    [SugarTable("sys_user")]
    public partial class SysUser
    {
           public SysUser(){

           }
           /// 
           /// Desc:主键
           /// Default:
           /// Nullable:False
           ///            
           [SugarColumn(IsPrimaryKey=true,IsIdentity=true,ColumnName="id")]
           public long Id {get;set;}

           /// 
           /// Desc:用户名
           /// Default:
           /// Nullable:False
           ///            
           [SugarColumn(ColumnName="user_name")]
           public string UserName {get;set;}

           /// 
           /// Desc:用户姓名
           /// Default:
           /// Nullable:True
           ///            
           [SugarColumn(ColumnName="real_name")]
           public string RealName {get;set;}

           /// 
           /// Desc:用户密码
           /// Default:
           /// Nullable:False
           ///            
           [SugarColumn(ColumnName="password")]
           public string Password {get;set;}

           /// 
           /// Desc:备注
           /// Default:
           /// Nullable:True
           ///            
           [SugarColumn(ColumnName="remark")]
           public string Remark {get;set;}

           /// 
           /// Desc:创建者ID
           /// Default:
           /// Nullable:False
           ///            
           [SugarColumn(ColumnName="create_userid")]
           public string CreateUserid {get;set;}

           /// 
           /// Desc:创建时间
           /// Default:
           /// Nullable:False
           ///            
           [SugarColumn(ColumnName="create_time")]
           public DateTime CreateTime {get;set;}

           /// 
           /// Desc:更新者ID
           /// Default:
           /// Nullable:True
           ///            
           [SugarColumn(ColumnName="update_userid")]
           public string UpdateUserid {get;set;}

           /// 
           /// Desc:更新时间
           /// Default:
           /// Nullable:True
           ///            
           [SugarColumn(ColumnName="update_time")]
           public DateTime? UpdateTime {get;set;}

    }
}

测试配置及代码

Dapper.LiteSql net461

public class LiteSqlFactory
{
    #region 变量
    private static ILiteSqlClient _liteSqlClient = new LiteSqlClient("Data Source=localhost;Port=3306;User ID=root;Password=123456;Initial Catalog=litesql_test;Charset=utf8mb4;SslMode=none;Allow User Variables=True;", DBType.MySQL, new MySQLProvider());
    #endregion

    #region 获取 ISession
    /// 
    /// 获取 ISession
    /// 
    /// 分表映射
    public static ISession GetSession(SplitTableMapping splitTableMapping = null)
    {
        return _liteSqlClient.GetSession(splitTableMapping);
    }
    #endregion

    #region 获取 ISession (异步)
    /// 
    /// 获取 ISession (异步)
    /// 
    /// 分表映射
    public static async Task GetSessionAsync(SplitTableMapping splitTableMapping = null)
    {
        return await _liteSqlClient.GetSessionAsync(splitTableMapping);
    }
    #endregion

}
using DAL;
using Dapper.LiteSql;
using Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Utils;

namespace PerformanceTest
{
    public partial class Form1 : Form
    {
        #region 变量
        private BsOrderDal m_BsOrderDal = ServiceHelper.Get();
        private SysUserDal m_SysUserDal = ServiceHelper.Get();
        private Random _rnd = new Random();
        private int _count = 10000;
        private bool _printSql = false;
        #endregion

        #region Form1
        public Form1()
        {
            InitializeComponent();
        }
        #endregion

        #region Form1_Load
        private void Form1_Load(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                LiteSqlFactory.GetSession();  //预热
                Log("预热完成");
            });
        }
        #endregion

        #region Log
        private void Log(string log)
        {
            if (!this.IsDisposed)
            {
                string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "rnrn";

                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        textBox1.AppendText(msg);
                    }));
                }
                else
                {
                    textBox1.AppendText(msg);
                }
            }
        }
        #endregion

        #region 清空输出框
        private void button10_Click(object sender, EventArgs e)
        {
            textBox1.Text = string.Empty;
        }
        #endregion

        #region RunTask
        private Task RunTask(Action action)
        {
            return Task.Run(() =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                    throw;
                }
            });
        }

        private Task RunTask(Action action, T t)
        {
            return Task.Factory.StartNew(obj =>
            {
                try
                {
                    action((T)obj);
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                    throw;
                }
            }, t);
        }
        #endregion

        #region cbxPrintSql_Click
        private void cbxPrintSql_Click(object sender, EventArgs e)
        {
            _printSql = cbxPrintSql.Checked;
        }
        #endregion

        #region 删除
        private void button5_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Log("删除 开始");
                var session = LiteSqlFactory.GetSession();
                session.CreateSql("id>@Id", 12).DeleteByCondition();
                Log("删除 完成");
            });
        }
        #endregion

        #region 测试批量修改
        private void button3_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List userList = m_SysUserDal.GetList("select t.* from sys_user t where t.id > 20");

                Log("批量修改 开始 count=" + userList.Count);
                DateTime dt = DateTime.Now;

                var session = LiteSqlFactory.GetSession();
                if (_printSql)
                {
                    session.OnExecuting = (s, p) => Console.WriteLine(s); //打印SQL
                }

                try
                {
                    session.AttachOld(userList);
                    foreach (SysUser user in userList)
                    {
                        user.Remark = "测试修改用户" + _rnd.Next(1, 10000);
                        user.UpdateUserid = "1";
                        user.UpdateTime = DateTime.Now;
                    }
                    userList.ForEach(item => item.UpdateTime = DateTime.Now);

                    session.BeginTransaction();
                    session.Update(userList);
                    session.CommitTransaction();
                }
                catch (Exception ex)
                {
                    session.RollbackTransaction();
                    throw;
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 测试批量添加
        private void button4_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i  Console.WriteLine(s); //打印SQL
                }

                try
                {
                    session.BeginTransaction();
                    session.Insert(userList);
                    session.CommitTransaction();
                }
                catch
                {
                    session.RollbackTransaction();
                    throw;
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量添加 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 测试循环修改
        private void button7_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List userList = m_SysUserDal.GetList("select t.* from sys_user t where t.id > 20");

                Log("循环修改 开始 count=" + userList.Count);
                DateTime dt = DateTime.Now;

                var session = LiteSqlFactory.GetSession();
                if (_printSql)
                {
                    session.OnExecuting = (s, p) => Console.WriteLine(s); //打印SQL
                }

                try
                {
                    session.AttachOld(userList);
                    foreach (SysUser user in userList)
                    {
                        user.Remark = "测试修改用户" + _rnd.Next(1, 10000);
                        user.UpdateUserid = "1";
                        user.UpdateTime = DateTime.Now;
                    }

                    session.BeginTransaction();
                    foreach (SysUser user in userList)
                    {
                        session.Update(user);
                    }
                    session.CommitTransaction();
                }
                catch
                {
                    session.RollbackTransaction();
                    throw;
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 测试循环添加
        private void button6_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i  Console.WriteLine(s); //打印SQL
                }

                try
                {
                    session.BeginTransaction();
                    foreach (SysUser user in userList)
                    {
                        session.Insert(user);
                    }
                    session.CommitTransaction();
                }
                catch
                {
                    session.RollbackTransaction();
                    throw;
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环添加 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 查询
        private void button1_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Log("查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i  @id 
                        and t.real_name like @remark", 20, "%测试%");

                    sql.Append(" order by t.create_time desc, t.id asc");

                    List userList = sql.QueryList();
                    Log("查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 分页查询
        private void button2_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Log("分页查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i  userList = new List();
                    for (int page = 1; page  @id 
                            and t.real_name like @remark", 20, "%测试%");

                        string orderby = " order by t.create_time desc, t.id asc";

                        userList.AddRange(sql.QueryPage(orderby, pageSize, page));
                    }
                    Log("分页查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("分页查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 并发查询
        private void button8_Click(object sender, EventArgs e)
        {
            ThreadPool.SetMaxThreads(1000, 1000);
            ThreadPool.SetMinThreads(200, 200);

            RunTask(() =>
            {
                Log("并发查询 开始");
                DateTime dt = DateTime.Now;

                List tasks = new List();
                for (int i = 1; i 
                    {
                        var session = LiteSqlFactory.GetSession();

                        ISqlString sql = session.CreateSql(@"
                            select t.* 
                            from sys_user t 
                            where t.id > @id 
                            and t.real_name like @remark", 20, "%测试%");

                        sql.Append(" order by t.create_time desc, t.id asc");

                        List userList = sql.QueryList();
                        if (index % 50 == 0) Log("第" + index + "次查询结果 count=" + userList.Count);
                    });
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 并发插入
        private void button9_Click(object sender, EventArgs e)
        {
            ThreadPool.SetMaxThreads(1000, 1000);
            ThreadPool.SetMinThreads(200, 200);

            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i  tasks = new List();
                foreach (SysUser item in userList)
                {
                    var task = RunTask(user =>
                    {
                        LiteSqlFactory.GetSession().Insert(user);
                    }, item);
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发插入 完成,耗时:" + time + "秒");
            });
        }
        #endregion

    }
}

FreeSql net461

public class FreeSqlUtil
{
    #region CreateFreeSqlClient
    public static IFreeSql CreateFreeSqlClient()
    {
        IFreeSql db = new FreeSql.FreeSqlBuilder()
            .UseConnectionString(FreeSql.DataType.MySql, @"Data Source=localhost;Port=3306;User ID=root;Password=123456;Initial Catalog=freesql_test;Charset=utf8mb4;SslMode=none;Allow User Variables=True;")
            .UseGenerateCommandParameterWithLambda(true)
            .Build(); //请务必定义成 Singleton 单例模式

        return db;
    }
    #endregion

}
using Models;
using NLog;
using FreeSqlDemo.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using FreeSql.Aop;
using Newtonsoft.Json;
using System.Threading;

namespace FreeSqlDemo
{
    public partial class Form1 : Form
    {
        #region 变量
        private Logger _log = NLog.LogManager.GetCurrentClassLogger();
        private IFreeSql _db;
        private int _count = 10000;
        private bool _printSql = false;
        #endregion

        #region Form1
        public Form1()
        {
            InitializeComponent();
        }
        #endregion

        #region Form1_Load
        private void Form1_Load(object sender, EventArgs e)
        {
            _db = FreeSqlUtil.CreateFreeSqlClient();

            if (_printSql)
            {
                _db.Aop.CurdAfter += CurdAfter;
            }

            RunTask(() =>
            {
                _db.Queryable().Count(); //预热
                Log("预热完成");
            });
        }
        #endregion

        #region Log
        private void Log(string log)
        {
            if (!this.IsDisposed)
            {
                string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "rnrn";

                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        textBox1.AppendText(msg);
                    }));
                }
                else
                {
                    textBox1.AppendText(msg);
                }
            }
        }
        #endregion

        #region 清空输出框
        private void button10_Click(object sender, EventArgs e)
        {
            textBox1.Text = string.Empty;
        }
        #endregion

        #region RunTask
        private Task RunTask(Action action)
        {
            return Task.Run(() =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    Log(ex.Message + "rn" + ex.StackTrace);
                }
            });
        }

        private Task RunTask(Action action, T t)
        {
            return Task.Factory.StartNew(obj =>
            {
                try
                {
                    action((T)obj);
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                    throw;
                }
            }, t);
        }
        #endregion

        #region 打印SQL
        private void CurdAfter(object sender, CurdAfterEventArgs e)
        {
            if (_printSql)
            {
                RunTask(() =>
                {
                    string msg = "SQL:" + e.Sql + "rnParam:" + JsonConvert.SerializeObject(e.DbParms.ToDictionary(it => it.ParameterName, it => it.Value));
                    Console.WriteLine(msg);
                    _log.Debug(msg);
                });
            }
        }
        #endregion

        #region cbxPrintSql_Click
        private void cbxPrintSql_Click(object sender, EventArgs e)
        {
            _printSql = cbxPrintSql.Checked;
        }
        #endregion

        #region 生成实体类
        private void button1_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Log("开始生成实体类");
                Log("生成实体类完成");
            });
        }
        #endregion

        #region 测试查询
        private void button2_Click(object sender, EventArgs e)
        {
            Log("开始查询");
            SysUser conditionModel = new SysUser();
            conditionModel.Remark = "管理员";
            string remark = "管理员";
            List list = _db.Queryable().Where(t => t.Id  new DateTime(2010, 1, 1)).ToList();
            foreach (SysUser user in list)
            {
                Log(string.Format("{0},{1},{2},{3}", user.UserName, user.RealName, user.Remark, user.CreateTime.ToString("yyyy-MM-dd")));
            }
            Log("查询结束 count=" + list.Count);
        }
        #endregion

        #region 测试批量修改
        private void button3_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Random rnd = new Random();
                List userList = _db.Queryable().Where(t => t.Id > 20).ToList();
                Log("批量修改 开始 count=" + userList.Count.ToString("0 000"));
                foreach (SysUser user in userList)
                {
                    user.Remark = "测试修改用户" + rnd.Next(0, 10000);
                    user.UpdateUserid = "1";
                    user.UpdateTime = DateTime.Now;
                }

                DateTime dt = DateTime.Now;

                _db.Ado.Transaction(() =>
                {
                    _db.Update().SetSource(userList).ExecuteAffrows();
                });

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 测试批量添加
        private void button4_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i 
                {
                    _db.Insert(userList).ExecuteAffrows();
                });

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量添加 结束,完成:" + time + "秒");
            });
        }
        #endregion

        #region 删除
        private void button5_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Log("删除 开始");
                _db.Delete().Where(t => t.Id > 20).ExecuteAffrows();
                Log("删除 完成");
            });
        }
        #endregion

        #region 测试循环修改
        private void button7_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Random rnd = new Random();
                List userList = _db.Queryable().Where(t => t.Id > 20).ToList();
                Log("循环修改 开始 count=" + userList.Count.ToString("0 000"));

                DateTime dt = DateTime.Now;

                _db.Ado.Transaction(() =>
                {
                    var repo = _db.GetRepository();

                    foreach (SysUser user in userList)
                    {
                        repo.Attach(user);
                    }

                    foreach (SysUser user in userList)
                    {
                        user.Remark = "测试修改用户" + rnd.Next(0, 10000);
                        user.UpdateUserid = "1";
                        user.UpdateTime = DateTime.Now;
                    }

                    foreach (SysUser user in userList)
                    {
                        repo.Update(user);
                    }
                });

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 测试循环添加
        private void button6_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i 
                {
                    foreach (SysUser user in userList)
                    {
                        _db.Insert(user).ExecuteIdentity();
                    }
                });

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环添加 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 查询
        private void button9_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                _db.Queryable().Where(t => t.Id == 1).ToList(); //预热

                Log("查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i  userList = _db.Queryable().Where(t => t.Id > 20 && t.RealName.Contains("测试")).OrderByDescending(t => t.CreateTime).OrderBy(t => t.Id).ToList();
                    Log("查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 分页查询
        private void button8_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                _db.Queryable().Where(t => t.Id == 1).ToList(); //预热

                Log("分页查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i ().Count();
                    int pageSize = 100;
                    int pageCount = (int)((total - 1) / pageSize + 1);
                    List userList = new List();
                    for (int page = 1; page ().Where(t => t.Id > 20 && t.RealName.Contains("测试")).OrderByDescending(t => t.CreateTime).OrderBy(t => t.Id).Page(page, pageSize).ToList());
                    }
                    Log("分页查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("分页查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 并发查询
        private void button11_Click(object sender, EventArgs e)
        {
            ThreadPool.SetMaxThreads(1000, 1000);
            ThreadPool.SetMinThreads(200, 200);

            RunTask(() =>
            {
                Log("并发查询 开始");
                DateTime dt = DateTime.Now;

                List tasks = new List();
                for (int i = 1; i 
                    {
                        List userList = _db.Queryable()
                            .Where(t => t.Id > 20 && t.RealName.Contains("测试"))
                            .OrderByDescending(t => t.CreateTime).OrderBy(t => t.Id).ToList();
                        if (index % 50 == 0) Log("第" + index + "次查询结果 count=" + userList.Count);
                    });
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 并发插入
        private void button12_Click(object sender, EventArgs e)
        {
            ThreadPool.SetMaxThreads(1000, 1000);
            ThreadPool.SetMinThreads(200, 200);

            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i  tasks = new List();
                foreach (SysUser item in userList)
                {
                    var task = RunTask(user =>
                    {
                        _db.Insert(user).ExecuteIdentity();
                    }, item);
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发插入 完成,耗时:" + time + "秒");
            });
        }
        #endregion

    }
}

SqlSugar net461

public class SqlSugarUtil
{
    public static readonly string ConnectionString = "Data Source=localhost;Port=3306;User ID=root;Password=123456;Initial Catalog=sqlsugar_test;Charset=utf8mb4;SslMode=none;Allow User Variables=True;";

    #region CreateSqlSugarClient
    public static SqlSugarScope CreateSqlSugarClient()
    {
        SqlSugarScope db = new SqlSugarScope(new ConnectionConfig()
        {
            ConnectionString = ConnectionString,//连接符字串
            DbType = SqlSugar.DbType.MySql, //数据库类型
            IsAutoCloseConnection = true //不设成true要手动close
        });

        return db;
    }
    #endregion

    #region CreateModels 生成实体类
    /// 
    /// 生成实体类
    /// 
    public static void CreateModels(SqlSugarClient db, string tableName = null)
    {
        ......此处省略
    }
    #endregion

}
using Models;
using NLog;
using SqlSugar;
using SqlSugarDemo.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SqlSugarDemo
{
    public partial class Form1 : Form
    {
        #region 变量
        private Logger _log = NLog.LogManager.GetCurrentClassLogger();
        private SqlSugarScope _db;
        private int _count = 10000;
        private bool _printSql = false;
        #endregion

        #region Form1
        public Form1()
        {
            InitializeComponent();
        }
        #endregion

        #region Form1_Load
        private void Form1_Load(object sender, EventArgs e)
        {
            _db = SqlSugarUtil.CreateSqlSugarClient();

            if (_printSql)
            {
                _db.Aop.OnLogExecuting = OnLogExecuting;
            }

            RunTask(() =>
            {
                _db.Queryable().Count(); //预热
                Log("预热完成");
            });
        }
        #endregion

        #region Log
        private void Log(string log)
        {
            if (!this.IsDisposed)
            {
                string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "rnrn";

                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        textBox1.AppendText(msg);
                    }));
                }
                else
                {
                    textBox1.AppendText(msg);
                }
            }
        }
        #endregion

        #region 清空输出框
        private void button10_Click(object sender, EventArgs e)
        {
            textBox1.Text = string.Empty;
        }
        #endregion

        #region RunTask
        private Task RunTask(Action action)
        {
            return Task.Run(() =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    Log(ex.Message + "rn" + ex.StackTrace);
                }
            });
        }

        private Task RunTask(Action action, T t)
        {
            return Task.Factory.StartNew(obj =>
            {
                try
                {
                    action((T)obj);
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                }
            }, t);
        }
        #endregion

        #region cbxPrintSql_Click
        private void cbxPrintSql_CheckedChanged(object sender, EventArgs e)
        {
            _printSql = cbxPrintSql.Checked;
        }
        #endregion

        #region 打印SQL
        private void OnLogExecuting(string sql, SugarParameter[] paramArr)
        {
            if (_printSql)
            {
                RunTask(() =>
                {
                    //string msg = "SQL:" + sql + "rnParam:" + _db.Utilities.SerializeObject(paramArr.ToDictionary(it => it.ParameterName, it => it.Value));
                    Console.WriteLine(sql);
                    _log.Debug(sql);
                });
            }
        }
        #endregion

        #region 生成实体类
        private void button1_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Log("开始生成实体类");
                SqlSugarUtil.CreateModels(new SqlSugarClient(new ConnectionConfig()
                {
                    ConnectionString = SqlSugarUtil.ConnectionString,//连接符字串
                    DbType = SqlSugar.DbType.MySql, //数据库类型
                    IsAutoCloseConnection = true //不设成true要手动close
                }));
                Log("生成实体类完成");
            });
        }
        #endregion

        #region 测试查询
        private void button2_Click(object sender, EventArgs e)
        {
            Log("开始查询");
            SysUser conditionModel = new SysUser();
            conditionModel.Remark = "管理员";
            string remark = "管理员";
            List list = _db.Queryable().Where(t => t.Id  new DateTime(2010, 1, 1)).ToList();
            foreach (SysUser user in list)
            {
                Log(string.Format("{0},{1},{2},{3}", user.UserName, user.RealName, user.Remark, user.CreateTime.ToString("yyyy-MM-dd")));
            }
            Log("查询结束 count=" + list.Count);
        }
        #endregion

        #region 测试批量修改
        private void button3_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Random rnd = new Random();
                List userList = _db.Queryable().Where(t => t.Id > 20).ToList();
                Log("批量修改 开始 count=" + userList.Count.ToString("0 000"));
                foreach (SysUser user in userList)
                {
                    user.Remark = "测试修改用户" + rnd.Next(0, 10000);
                    user.UpdateUserid = "1";
                    user.UpdateTime = DateTime.Now;
                }

                DateTime dt = DateTime.Now;
                try
                {
                    _db.Ado.BeginTran();
                    _db.Updateable(userList).ExecuteCommand();
                    _db.Ado.CommitTran();
                }
                catch (Exception ex)
                {
                    _db.Ado.RollbackTran();
                    throw ex;
                }
                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 测试批量添加
        private void button4_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i 
            {
                Log("删除 开始");
                _db.Deleteable(t => t.Id > 20).ExecuteCommand();
                Log("删除 完成");
            });
        }
        #endregion

        #region 测试循环修改
        private void button7_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Random rnd = new Random();
                List userList = _db.Queryable().Where(t => t.Id > 20).ToList();
                Log("循环修改 开始 count=" + userList.Count.ToString("0 000"));
                foreach (SysUser user in userList)
                {
                    user.Remark = "测试修改用户" + rnd.Next(0, 10000);
                    user.UpdateUserid = "1";
                    user.UpdateTime = DateTime.Now;
                }

                DateTime dt = DateTime.Now;
                try
                {
                    _db.Ado.BeginTran();
                    foreach (SysUser user in userList)
                    {
                        _db.Updateable(user).ExecuteCommand();
                    }
                    _db.Ado.CommitTran();
                }
                catch (Exception ex)
                {
                    _db.Ado.RollbackTran();
                    throw ex;
                }
                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 测试循环添加
        private void button6_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i 
            {
                _db.Queryable().Where(t => t.Id == 1).ToList(); //预热

                Log("查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i  userList = _db.Queryable().Where(t => t.Id > 20 && t.RealName.Contains("测试")).OrderBy(t => t.CreateTime, OrderByType.Desc).OrderBy(t => t.Id).ToList();
                    Log("查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 分页查询
        private void button8_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                _db.Queryable().Where(t => t.Id == 1).ToList(); //预热

                Log("分页查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i ().Count();
                    int pageSize = 100;
                    int pageCount = (total - 1) / pageSize + 1;
                    List userList = new List();
                    for (int page = 1; page ().Where(t => t.Id > 20 && t.RealName.Contains("测试")).OrderBy(t => t.CreateTime, OrderByType.Desc).OrderBy(t => t.Id).ToPageList(page, pageSize));
                    }
                    Log("分页查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("分页查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 并发查询
        private void button11_Click(object sender, EventArgs e)
        {
            ThreadPool.SetMaxThreads(1000, 1000);
            ThreadPool.SetMinThreads(200, 200);

            RunTask(() =>
            {
                Log("并发查询 开始");
                DateTime dt = DateTime.Now;

                List tasks = new List();
                for (int i = 1; i 
                    {
                        List userList = _db.Queryable().Where(t => t.Id > 20 && t.RealName.Contains("测试")).OrderBy(t => t.CreateTime, OrderByType.Desc).OrderBy(t => t.Id).ToList();
                        if (index % 50 == 0) Log("第" + index + "次查询结果 count=" + userList.Count);
                    });
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 并发插入
        private void button12_Click(object sender, EventArgs e)
        {
            ThreadPool.SetMaxThreads(1000, 1000);
            ThreadPool.SetMinThreads(200, 200);

            RunTask(() =>
            {
                List userList = new List();
                for (int i = 1; i  tasks = new List();
                foreach (SysUser item in userList)
                {
                    var task = RunTask(user =>
                    {
                        _db.Insertable(user).ExecuteCommand();
                    }, item);
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发插入 完成,耗时:" + time + "秒");
            });
        }
        #endregion

    }
}

Fast.Framework net6

using Fast.Framework;
using Fast.Framework.Interfaces;
using Fast.Framework.Models;
using Fast.Framework.Extensions;
using Fast.Framework.Aop;
using Models;

namespace FastFrameworkDemo
{
    public partial class Form1 : Form
    {
        #region 变量
        private Random _rnd = new Random();
        private int _count = 10000;
        private bool _printSql = false;
        #endregion

        #region Form1
        public Form1()
        {
            InitializeComponent();
        }
        #endregion

        #region Form1_Load
        private void Form1_Load(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                await GetDbContext().Query().CountAsync();
                Log("预热完成");
            });
        }
        #endregion

        #region Log
        private void Log(string log)
        {
            if (!this.IsDisposed)
            {
                string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "rnrn";

                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        textBox1.AppendText(msg);
                    }));
                }
                else
                {
                    textBox1.AppendText(msg);
                }
            }
        }
        #endregion

        #region 清空输出框
        private void button10_Click(object sender, EventArgs e)
        {
            textBox1.Text = string.Empty;
        }
        #endregion

        #region RunTask
        private Task RunTask(Action action)
        {
            return Task.Run(() =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                }
            });
        }

        private Task RunTask(Action action, T t)
        {
            return Task.Factory.StartNew(obj =>
            {
                try
                {
                    action((T)obj);
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                }
            }, t);
        }
        #endregion

        #region cbxPrintSql_Click
        private void cbxPrintSql_Click(object sender, EventArgs e)
        {
            _printSql = cbxPrintSql.Checked;
        }
        #endregion

        #region GetDbContext
        private IDbContext GetDbContext()
        {
            IDbContext _db = new DbContext(new List() {
                    new DbOptions()
                    {
                      DbId = "1",
                      DbType = DbType.MySQL,
                      ProviderName = "MySqlConnector",
                      FactoryName = "MySqlConnector.MySqlConnectorFactory,MySqlConnector",
                      ConnectionStrings = "Data Source=localhost;Port=3306;User ID=root;Password=123456;Initial Catalog=fast_framework_test;Charset=utf8mb4;SslMode=none;Allow User Variables=True;"
                    }
                });

            if (_printSql)
            {
                _db.Aop.DbLog = (sql, dp) =>
                {
                    Console.WriteLine($"执行Sql:{sql}");
                    if (dp != null)
                    {
                        foreach (var item in dp)
                        {
                            Console.WriteLine($"参数名称:{item.ParameterName} 参数值:{item.Value}");
                        }
                    }
                };
            }

            return _db;
        }
        #endregion

        #region 删除
        private void button1_Click(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                Log("删除 开始");
                await GetDbContext().Delete().Where(t => t.Id > 20).ExceuteAsync();
                Log("删除 完成");
            });
        }
        #endregion

        #region 批量修改
        private void button2_Click(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                List userList = await GetDbContext().Query().Where(t => t.Id > 20).ToListAsync();

                Log("批量修改 开始 count=" + userList.Count);
                DateTime dt = DateTime.Now;

                try
                {
                    foreach (SysUser user in userList)
                    {
                        user.Remark = "测试修改用户" + _rnd.Next(1, 10000);
                        user.UpdateUserid = "1";
                        user.UpdateTime = DateTime.Now;
                    }

                    await GetDbContext().Update(userList).ExceuteAsync();
                }
                catch
                {
                    //todo:没有rollback?
                    throw;
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 批量添加
        private void button3_Click(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                List userList = new List();
                for (int i = 1; i 
            {
                List userList = await GetDbContext().Query().Where(t => t.Id > 20).ToListAsync();

                Log("循环修改 开始 count=" + userList.Count);
                DateTime dt = DateTime.Now;

                try
                {
                    foreach (SysUser user in userList)
                    {
                        user.Remark = "测试修改用户" + _rnd.Next(1, 10000);
                        user.UpdateUserid = "1";
                        user.UpdateTime = DateTime.Now;
                    }

                    var db = GetDbContext();
                    await db.Ado.BeginTranAsync();
                    foreach (SysUser user in userList)
                    {
                        await db.Update(user).ExceuteAsync();
                    }
                    await db.Ado.CommitTranAsync();
                }
                catch
                {
                    //todo:没有rollback?
                    throw;
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 循环添加
        private void button5_Click(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                List userList = new List();
                for (int i = 1; i 
            {
                Log("查询 开始");
                DateTime dt = DateTime.Now;

                var db = GetDbContext();
                for (int i = 0; i  userList = await db.Query()
                        .Where(t => t.Id > 20 && t.RealName.Contains("%测试%"))
                        .OrderBy("create_time", "desc")
                        .OrderBy("id", "asc").ToListAsync();
                    Log("查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 分页查询
        private void button7_Click(object sender, EventArgs e)
        {
            Log("尚未实现");
        }
        #endregion

        #region 并发查询
        private void button8_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                ThreadPool.SetMaxThreads(1000, 1000);
                ThreadPool.SetMinThreads(200, 200);

                Log("并发查询 开始");
                DateTime dt = DateTime.Now;

                List tasks = new List();
                for (int i = 1; i 
                    {
                        List userList = await GetDbContext().Query()
                            .Where(t => t.Id > 20 && t.RealName.Contains("%测试%"))
                            .OrderBy("create_time", "desc")
                            .OrderBy("id", "asc").ToListAsync();
                        if (index % 50 == 0) Log("第" + index + "次查询结果 count=" + userList.Count);
                    });
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 并发插入
        private void button9_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                ThreadPool.SetMaxThreads(1000, 1000);
                ThreadPool.SetMinThreads(200, 200);

                List userList = new List();
                for (int i = 1; i  tasks = new List();
                foreach (SysUser item in userList)
                {
                    var task = RunTask(async user =>
                    {
                        await GetDbContext().Insert(user).ExceuteAsync();
                    }, item);
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发插入 完成,耗时:" + time + "秒");
            });
        }
        #endregion

    }
}

Dapper.LiteSql net6

using Dapper.LiteSql;
using Models;
using Provider;

namespace DapperLiteSqlDemo
{
    public partial class Form1 : Form
    {
        #region 变量
        private Random _rnd = new Random();
        private int _count = 10000;
        private bool _showSqlLog = false;
        private ILiteSqlClient _db;
        private bool _printSql = false;
        #endregion

        #region Form1
        public Form1()
        {
            InitializeComponent();
        }
        #endregion

        #region Form1_Load
        private void Form1_Load(object sender, EventArgs e)
        {
            _db = new LiteSqlClient("Data Source=localhost;Port=3306;User ID=root;Password=123456;Initial Catalog=litesql_test;Charset=utf8mb4;SslMode=none;Allow User Variables=True;",
                DBType.MySQL, new MySQLProvider());

            RunTask(() =>
            {
                _db.GetSession(); //预热
                Log("预热完成");
            });
        }
        #endregion

        #region Log
        private void Log(string log)
        {
            if (!this.IsDisposed)
            {
                string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "rnrn";

                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        textBox1.AppendText(msg);
                    }));
                }
                else
                {
                    textBox1.AppendText(msg);
                }
            }
        }
        #endregion

        #region 清空输出框
        private void button10_Click(object sender, EventArgs e)
        {
            textBox1.Text = string.Empty;
        }
        #endregion

        #region RunTask
        private Task RunTask(Action action)
        {
            return Task.Run(() =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                    throw;
                }
            });
        }

        private Task RunTask(Action action, T t)
        {
            return Task.Factory.StartNew(obj =>
            {
                try
                {
                    action((T)obj);
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                    throw;
                }
            }, t);
        }
        #endregion

        #region cbxPrintSql_Click
        private void cbxPrintSql_Click(object sender, EventArgs e)
        {
            _printSql = cbxPrintSql.Checked;
        }
        #endregion

        #region 删除
        private void button1_Click(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                Log("删除 开始");
                await _db.GetSession().CreateSql("id>@Id", 20).DeleteByConditionAsync();
                Log("删除 完成");
            });
        }
        #endregion

        #region 批量修改
        private void button2_Click(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                List userList = await _db.GetSession().Queryable().Where(t => t.Id > 20).ToListAsync();

                Log("批量修改 开始 count=" + userList.Count);
                DateTime dt = DateTime.Now;
                ISession? session = null;

                try
                {
                    foreach (SysUser user in userList)
                    {
                        user.Remark = "测试修改用户" + _rnd.Next(1, 10000);
                        user.UpdateUserid = "1";
                        user.UpdateTime = DateTime.Now;
                    }

                    session = await _db.GetSessionAsync();
                    session.BeginTransaction();
                    await session.UpdateAsync(userList);
                    session.CommitTransaction();
                }
                catch
                {
                    session?.RollbackTransaction();
                    throw;
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 批量添加
        private void button3_Click(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                List userList = new List();
                for (int i = 1; i 
            {
                List userList = await _db.GetSession().Queryable().Where(t => t.Id > 20).ToListAsync();

                Log("循环修改 开始 count=" + userList.Count);
                DateTime dt = DateTime.Now;
                ISession? session = null;

                try
                {
                    foreach (SysUser user in userList)
                    {
                        user.Remark = "测试修改用户" + _rnd.Next(1, 10000);
                        user.UpdateUserid = "1";
                        user.UpdateTime = DateTime.Now;
                    }

                    session = await _db.GetSessionAsync();
                    session.BeginTransaction();
                    foreach (SysUser user in userList)
                    {
                        await session.UpdateAsync(user);
                    }
                    session.CommitTransaction();
                }
                catch
                {
                    session?.RollbackTransaction();
                    throw;
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环修改 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 循环添加
        private void button5_Click(object sender, EventArgs e)
        {
            RunTask(async () =>
            {
                List userList = new List();
                for (int i = 1; i 
            {
                Log("查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i  userList = await _db.GetSession().Queryable()
                             .Where(t => t.Id > 20 && t.RealName.Contains("%测试%"))
                             .OrderByDescending(t => t.CreateTime)
                             .OrderBy(t => t.Id).ToListAsync();
                    Log("查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 分页查询
        private void button7_Click(object sender, EventArgs e)
        {
            Log("尚未实现");
        }
        #endregion

        #region 并发查询
        private void button8_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                ThreadPool.SetMaxThreads(1000, 1000);
                ThreadPool.SetMinThreads(200, 200);

                Log("并发查询 开始");
                DateTime dt = DateTime.Now;

                List tasks = new List();
                for (int i = 1; i 
                    {
                        List userList = await _db.GetSession().Queryable()
                            .Where(t => t.Id > 20 && t.RealName.Contains("%测试%"))
                            .OrderByDescending(t => t.CreateTime)
                            .OrderBy(t => t.Id).ToListAsync();
                        if (index % 50 == 0) Log("第" + index + "次查询结果 count=" + userList.Count);
                    });
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发查询 完成,耗时:" + time + "秒");
            });
        }
        #endregion

        #region 并发插入
        private void button9_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                ThreadPool.SetMaxThreads(1000, 1000);
                ThreadPool.SetMinThreads(200, 200);

                List userList = new List();
                for (int i = 1; i  tasks = new List();
                foreach (SysUser item in userList)
                {
                    var task = RunTask(async user =>
                    {
                        await _db.GetSession().InsertAsync(user);
                    }, item);
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("并发插入 完成,耗时:" + time + "秒");
            });
        }
        #endregion

    }
}

测试结果

常规测试

Dapper.LiteSql net461

ORM增删改查并发性能测试2插图1

FreeSql net461

ORM增删改查并发性能测试2插图2

SqlSugar net461

ORM增删改查并发性能测试2插图3

Fast.Framework net6

除了MySql.Data.dll还引用了MySqlConnector.dll (为什么net6?它不支持net framework)
ORM增删改查并发性能测试2插图4

Dapper.LiteSql net6

ORM增删改查并发性能测试2插图5

并发查询

Dapper.LiteSql net461

ORM增删改查并发性能测试2插图6

FreeSql net461

ORM增删改查并发性能测试2插图7

SqlSugar net461

ORM增删改查并发性能测试2插图8

Fast.Framework net6

除了MySql.Data.dll还引用了MySqlConnector.dll (为什么net6?它不支持net framework,环境不同,所以这个测试结果供参考,就不要计较了)
ORM增删改查并发性能测试2插图9

Dapper.LiteSql net6

(为了和Fast.Framework对比,确实慢,慢70%左右,可能是MySqlConnector.dll的功劳,它是真异步,只用MySql.Data.dll是假异步)
ORM增删改查并发性能测试2插图10

并发插入

Dapper.LiteSql net461

ORM增删改查并发性能测试2插图11

FreeSql net461

ORM增删改查并发性能测试2插图12

SqlSugar net461

ORM增删改查并发性能测试2插图13

Fast.Framework net6

除了MySql.Data.dll还引用了MySqlConnector.dll (为什么net6?它不支持net framework)
ORM增删改查并发性能测试2插图14

Dapper.LiteSql net6

(为了和Fast.Framework对比)
ORM增删改查并发性能测试2插图15

写在最后


我不偏向任何ORM,有一说一。
ORM的选择,性能固然重要,但性能差一点也不影响使用,主要是为了测试有没有硬伤,比如某个操作,一个ORM需要2秒,另一个ORM需要50秒,那50秒这个,慢了一个数量级还多,是不是有问题?再比如说某个测试,别的ORM,有耗时20秒的,有耗时30秒的,也有耗时70秒的,都问题不大,但有一个ORM,它报错了,是不是个问题?

这次并发测试,EF和EFCore我没有测试,因为我比较相信官方,可能它会慢一点,但因为用户量特别多,应该不会有硬伤。有兴趣的可以拿我的测试代码,稍微改一下测试测试EF和EFCore。
我自己写的LiteSql,算是个历史遗留问题,好几年前从上家公司的DBHelper一路改过来的,除非我把它完全删了,否则总想把它改好,这就需要测试,以保证质量。我因为写LiteSql,学了一些东西,技术上多多少少有进步,这就是意义。

文章来源于互联网:ORM增删改查并发性能测试2

THE END
分享
二维码