前言
上一篇《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
測驗程式中配置的資料連接字串
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
{
///<summary>
///用戶表
///</summary>
[SugarTable("sys_user")]
public partial class SysUser
{
public SysUser(){
}
/// <summary>
/// Desc:主鍵
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(IsPrimaryKey=true,IsIdentity=true,ColumnName="id")]
public long Id {get;set;}
/// <summary>
/// Desc:用戶名
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(ColumnName="user_name")]
public string UserName {get;set;}
/// <summary>
/// Desc:用戶姓名
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="real_name")]
public string RealName {get;set;}
/// <summary>
/// Desc:用戶密碼
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(ColumnName="password")]
public string Password {get;set;}
/// <summary>
/// Desc:備注
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="remark")]
public string Remark {get;set;}
/// <summary>
/// Desc:創建者ID
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(ColumnName="create_userid")]
public string CreateUserid {get;set;}
/// <summary>
/// Desc:創建時間
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(ColumnName="create_time")]
public DateTime CreateTime {get;set;}
/// <summary>
/// Desc:更新者ID
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="update_userid")]
public string UpdateUserid {get;set;}
/// <summary>
/// Desc:更新時間
/// Default:
/// Nullable:True
/// </summary>
[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
/// <summary>
/// 獲取 ISession
/// </summary>
/// <param name="splitTableMapping">分表映射</param>
public static ISession GetSession(SplitTableMapping splitTableMapping = null)
{
return _liteSqlClient.GetSession(splitTableMapping);
}
#endregion
#region 獲取 ISession (異步)
/// <summary>
/// 獲取 ISession (異步)
/// </summary>
/// <param name="splitTableMapping">分表映射</param>
public static async Task<ISession> 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<BsOrderDal>();
private SysUserDal m_SysUserDal = ServiceHelper.Get<SysUserDal>();
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 + "\r\n\r\n";
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<T>(Action<T> 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<SysUser>();
Log("洗掉 完成");
});
}
#endregion
#region 測驗批量修改
private void button3_Click(object sender, EventArgs e)
{
RunTask(() =>
{
List<SysUser> 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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("批量添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
var session = LiteSqlFactory.GetSession();
if (_printSql)
{
session.OnExecuting = (s, p) => 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<SysUser> 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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("回圈添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
var session = LiteSqlFactory.GetSession();
if (_printSql)
{
session.OnExecuting = (s, p) => 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 < 10; 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<SysUser> userList = sql.QueryList<SysUser>();
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 < 10; i++)
{
int total = m_SysUserDal.GetTotalCount();
int pageSize = 100;
int pageCount = (total - 1) / pageSize + 1;
var session = LiteSqlFactory.GetSession();
List<SysUser> userList = new List<SysUser>();
for (int page = 1; page <= pageCount; page++)
{
ISqlString sql = session.CreateSql(@"
select t.*
from sys_user t
where 1=1
and t.id > @id
and t.real_name like @remark", 20, "%測驗%");
string orderby = " order by t.create_time desc, t.id asc";
userList.AddRange(sql.QueryPage<SysUser>(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<Task> tasks = new List<Task>();
for (int i = 1; i <= 1000; i++)
{
int index = i;
Task task = RunTask(() =>
{
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<SysUser> userList = sql.QueryList<SysUser>();
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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Remark = "測驗插入用戶" + i;
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("并發插入 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
List<Task> tasks = new List<Task>();
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<SysUser>().Count(); //預熱
Log("預熱完成");
});
}
#endregion
#region Log
private void Log(string log)
{
if (!this.IsDisposed)
{
string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "\r\n\r\n";
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 + "\r\n" + ex.StackTrace);
}
});
}
private Task RunTask<T>(Action<T> 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 + "\r\nParam:" + 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<SysUser> list = _db.Queryable<SysUser>().Where(t => t.Id < 20 && t.Remark.Contains(conditionModel.Remark) && t.CreateTime > 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<SysUser> userList = _db.Queryable<SysUser>().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<SysUser>().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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("批量添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
_db.Ado.Transaction(() =>
{
_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<SysUser>().Where(t => t.Id > 20).ExecuteAffrows();
Log("洗掉 完成");
});
}
#endregion
#region 測驗回圈修改
private void button7_Click(object sender, EventArgs e)
{
RunTask(() =>
{
Random rnd = new Random();
List<SysUser> userList = _db.Queryable<SysUser>().Where(t => t.Id > 20).ToList();
Log("回圈修改 開始 count=" + userList.Count.ToString("0 000"));
DateTime dt = DateTime.Now;
_db.Ado.Transaction(() =>
{
var repo = _db.GetRepository<SysUser>();
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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("回圈添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
_db.Ado.Transaction(() =>
{
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<SysUser>().Where(t => t.Id == 1).ToList(); //預熱
Log("查詢 開始");
DateTime dt = DateTime.Now;
for (int i = 0; i < 10; i++)
{
List<SysUser> userList = _db.Queryable<SysUser>().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<SysUser>().Where(t => t.Id == 1).ToList(); //預熱
Log("分頁查詢 開始");
DateTime dt = DateTime.Now;
for (int i = 0; i < 10; i++)
{
long total = _db.Queryable<SysUser>().Count();
int pageSize = 100;
int pageCount = (int)((total - 1) / pageSize + 1);
List<SysUser> userList = new List<SysUser>();
for (int page = 1; page <= pageCount; page++)
{
userList.AddRange(_db.Queryable<SysUser>().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<Task> tasks = new List<Task>();
for (int i = 1; i <= 1000; i++)
{
int index = i;
Task task = RunTask(() =>
{
List<SysUser> userList = _db.Queryable<SysUser>()
.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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Remark = "測驗插入用戶" + i;
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("并發插入 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
List<Task> tasks = new List<Task>();
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 生成物體類
/// <summary>
/// 生成物體類
/// </summary>
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<SysUser>().Count(); //預熱
Log("預熱完成");
});
}
#endregion
#region Log
private void Log(string log)
{
if (!this.IsDisposed)
{
string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "\r\n\r\n";
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 + "\r\n" + ex.StackTrace);
}
});
}
private Task RunTask<T>(Action<T> 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 + "\r\nParam:" + _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<SysUser> list = _db.Queryable<SysUser>().Where(t => t.Id < 20 && t.Remark.Contains(conditionModel.Remark) && t.CreateTime > 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<SysUser> userList = _db.Queryable<SysUser>().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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("批量添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
try
{
_db.Ado.BeginTran();
_db.Insertable(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 button5_Click(object sender, EventArgs e)
{
RunTask(() =>
{
Log("洗掉 開始");
_db.Deleteable<SysUser>(t => t.Id > 20).ExecuteCommand();
Log("洗掉 完成");
});
}
#endregion
#region 測驗回圈修改
private void button7_Click(object sender, EventArgs e)
{
RunTask(() =>
{
Random rnd = new Random();
List<SysUser> userList = _db.Queryable<SysUser>().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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("回圈添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
try
{
_db.Ado.BeginTran();
foreach (SysUser user in userList)
{
_db.Insertable(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 button9_Click(object sender, EventArgs e)
{
RunTask(() =>
{
_db.Queryable<SysUser>().Where(t => t.Id == 1).ToList(); //預熱
Log("查詢 開始");
DateTime dt = DateTime.Now;
for (int i = 0; i < 10; i++)
{
List<SysUser> userList = _db.Queryable<SysUser>().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<SysUser>().Where(t => t.Id == 1).ToList(); //預熱
Log("分頁查詢 開始");
DateTime dt = DateTime.Now;
for (int i = 0; i < 10; i++)
{
int total = _db.Queryable<SysUser>().Count();
int pageSize = 100;
int pageCount = (total - 1) / pageSize + 1;
List<SysUser> userList = new List<SysUser>();
for (int page = 1; page <= pageCount; page++)
{
userList.AddRange(_db.Queryable<SysUser>().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<Task> tasks = new List<Task>();
for (int i = 1; i <= 1000; i++)
{
int index = i;
Task task = RunTask(() =>
{
List<SysUser> userList = _db.Queryable<SysUser>().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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Remark = "測驗插入用戶" + i;
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("并發插入 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
List<Task> tasks = new List<Task>();
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<SysUser>().CountAsync();
Log("預熱完成");
});
}
#endregion
#region Log
private void Log(string log)
{
if (!this.IsDisposed)
{
string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "\r\n\r\n";
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<T>(Action<T> 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<DbOptions>() {
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<SysUser>().Where(t => t.Id > 20).ExceuteAsync();
Log("洗掉 完成");
});
}
#endregion
#region 批量修改
private void button2_Click(object sender, EventArgs e)
{
RunTask(async () =>
{
List<SysUser> userList = await GetDbContext().Query<SysUser>().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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("批量添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
try
{
await GetDbContext().Insert(userList).ExceuteAsync();
}
catch
{
//todo:沒有rollback?
throw;
}
string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
Log("批量添加 完成,耗時:" + time + "秒");
});
}
#endregion
#region 回圈修改
private void button4_Click(object sender, EventArgs e)
{
RunTask(async () =>
{
List<SysUser> userList = await GetDbContext().Query<SysUser>().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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("回圈添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
try
{
var db = GetDbContext();
await db.Ado.BeginTranAsync();
foreach (SysUser user in userList)
{
await db.Insert(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 button6_Click(object sender, EventArgs e)
{
RunTask(async () =>
{
Log("查詢 開始");
DateTime dt = DateTime.Now;
var db = GetDbContext();
for (int i = 0; i < 10; i++)
{
List<SysUser> userList = await db.Query<SysUser>()
.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<Task> tasks = new List<Task>();
for (int i = 1; i <= 1000; i++)
{
int index = i;
Task task = RunTask(async () =>
{
List<SysUser> userList = await GetDbContext().Query<SysUser>()
.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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Remark = "測驗插入用戶" + i;
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("并發插入 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
List<Task> tasks = new List<Task>();
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 + "\r\n\r\n";
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<T>(Action<T> 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<SysUser>();
Log("洗掉 完成");
});
}
#endregion
#region 批量修改
private void button2_Click(object sender, EventArgs e)
{
RunTask(async () =>
{
List<SysUser> userList = await _db.GetSession().Queryable<SysUser>().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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("批量添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
ISession? session = null;
try
{
session = await _db.GetSessionAsync();
session.BeginTransaction();
await session.InsertAsync(userList);
session.CommitTransaction();
}
catch
{
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(async () =>
{
List<SysUser> userList = await _db.GetSession().Queryable<SysUser>().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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("回圈添加 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
ISession? session = null;
try
{
session = await _db.GetSessionAsync();
session.BeginTransaction();
foreach (SysUser user in userList)
{
await session.InsertAsync(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(async () =>
{
Log("查詢 開始");
DateTime dt = DateTime.Now;
for (int i = 0; i < 10; i++)
{
List<SysUser> userList = await _db.GetSession().Queryable<SysUser>()
.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<Task> tasks = new List<Task>();
for (int i = 1; i <= 1000; i++)
{
int index = i;
Task task = RunTask(async () =>
{
List<SysUser> userList = await _db.GetSession().Queryable<SysUser>()
.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<SysUser> userList = new List<SysUser>();
for (int i = 1; i <= _count; i++)
{
SysUser user = new SysUser();
user.UserName = "testUser";
user.RealName = "測驗插入用戶";
user.Remark = "測驗插入用戶" + i;
user.Password = "123456";
user.CreateUserid = "1";
user.CreateTime = DateTime.Now;
userList.Add(user);
}
Log("并發插入 開始 count=" + userList.Count);
DateTime dt = DateTime.Now;
List<Task> tasks = new List<Task>();
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
FreeSql net461
SqlSugar net461
Fast.Framework net6
除了MySql.Data.dll還參考了MySqlConnector.dll (為什么net6?它不支持net framework)
Dapper.LiteSql net6
并發查詢
Dapper.LiteSql net461
FreeSql net461
SqlSugar net461
Fast.Framework net6
除了MySql.Data.dll還參考了MySqlConnector.dll (為什么net6?它不支持net framework,環境不同,所以這個測驗結果供參考,就不要計較了)
Dapper.LiteSql net6
(為了和Fast.Framework對比,確實慢,慢70%左右,可能是MySqlConnector.dll的功勞,它是真異步,只用MySql.Data.dll是假異步)
并發插入
Dapper.LiteSql net461
FreeSql net461
SqlSugar net461
Fast.Framework net6
除了MySql.Data.dll還參考了MySqlConnector.dll (為什么net6?它不支持net framework)
Dapper.LiteSql net6
(為了和Fast.Framework對比)
寫在最后
我不偏向任何ORM,有一說一,ORM的選擇,性能固然重要,但性能差一點也不影響使用,主要是為了測驗有沒有硬傷,比如某個操作,一個ORM需要2秒,另一個ORM需要50秒,那50秒這個,慢了一個數量級還多,是不是有問題?再比如說某個測驗,別的ORM,有耗時20秒的,有耗時30秒的,也有耗時70秒的,都問題不大,但有一個ORM,它報錯了,是不是個問題?
這次并發測驗,EF和EFCore我沒有測驗,因為我比較相信官方,可能它會慢一點,但因為用戶量特別多,應該不會有硬傷,有興趣的可以拿我的測驗代碼,稍微改一下測驗測驗EF和EFCore,
我自己寫的LiteSql,算是個歷史遺留問題,好幾年前從上家公司的DBHelper一路改過來的,除非我把它完全刪了,否則總想把它改好,這就需要測驗,以保證質量,我因為寫LiteSql,學了一些東西,技術上多多少少有進步,這就是意義,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/506468.html
標籤:C#
上一篇:如何在C中讀取并列印字串陣列?