using CSFramework.DB;
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 CSFramework.DBTester
{
///
/// C/S框架网,CSFramework.DB,C/S框架数据库并发测试
///
public partial class frmSQLConcurrentTester : Form
{
static object _threadCount = 0;//线程数量
static object _connCount = 0;//已建立的SQL连接数
static List _threadList = new List();//线程数量
static DateTime _startTime = DateTime.Now;
static List _DocNos = new List();//本次测试生成的单据号码
static object _ThreadFinish = 0;
static object _Rows_Inserted = 0;
static object _Rows_Updated = 0;
static object _Rows_Deleted = 0;
static object _Failed = 0;
public frmSQLConcurrentTester()
{
InitializeComponent();
}
private void btnTest_Click(object sender, EventArgs e)
{
txtResult.Text = "";
OnResult("开始测试...");
btnTest.Enabled = false;
_connCount = 0;
_threadCount = 0;
_Failed = 0;
_ThreadFinish = 0;
_Rows_Inserted = 0;
_Rows_Updated = 0;
_Rows_Deleted = 0;
_startTime = DateTime.Now;
_DocNos.Clear();
//初始化进度条
this.DoPrepareProgress();
//启动多线程
int t = int.Parse(txtThreads.Text);
int count = 1;
while (count <= t)
{
Task.Run(() => { DoThread(); });
Application.DoEvents();
count++;
}
//等待全部线程完成处理
Thread.Sleep(1000); //必须等待第1个线程
WaitThreads();
OnResult($"本次测试用户数据, Insert={_Rows_Inserted},Update={_Rows_Updated},Delete={_Rows_Deleted},失败数={_Failed}");
OnResult("测试结束...");
TimeSpan ts = DateTime.Now - _startTime;
lblTime.Text = "用时:" + ts.TotalSeconds.ToString() + "秒.";
btnTest.Enabled = true;
btnTest.Invalidate();
GC.Collect();//回收垃圾
}
///
/// 等待线程
///
private void WaitThreads()
{
while (int.Parse(_ThreadFinish.ToString()) < int.Parse(txtThreads.Text))
{
//处理线程....
Application.DoEvents();
}
}
///
/// 启动一个线程
///
private void DoThread()
{
try
{
//线程任务计数器
lock (_threadCount)
{
_threadCount = int.Parse(_threadCount.ToString()) + 1;
}
int currentID = int.Parse(_threadCount.ToString());
if (currentID > int.Parse(txtThreads.Text)) return;
lock (_threadList) _threadList.Add(currentID);
this.Invoke(new SyncCall(this.OnResult), new object[] { "开始线程:" + currentID.ToString() });
string connStr = "";
//本地连接
if (rbConnLocal.Checked)
connStr = "Server =.; Database = CSFrameworkV5_Normal; User ID = sa; Password = test;";
else//远程连接
connStr = "Server =120.77.22.34; Database = CSFrameworkV5_Normal; User ID = sa; Password = test;";
//启动线程池
if (chkPooling.Checked)
connStr = connStr + "pooling = true; connection lifetime = 0; min pool size = 1; max pool size = 32767";
else
connStr = connStr + "pooling = false; ";
string SQL = "INSERT INTO tb_QO(QONO,DocDate,CustomerCode,RefPONO,Currency,Sales,CreationDate,CreatedBy,LastUpdateDate,LastUpdatedBy)" +
"VALUES(@QONO, @DocDate, @CustomerCode, @RefPONO, @Currency, @Sales, @CreationDate, @CreatedBy, @LastUpdateDate, @LastUpdatedBy)";
string SQL1 = "UPDATE tb_QO SET Client=@Client,Remark=@Remark,LastUpdateDate=@LastUpdateDate WHERE QONO=@QONO";
string SQL2 = "DELETE tb_QO WHERE QONO=@QONO";
int sub_total = 0;
int go = 0;
CommandHelper cmd = null;
while (int.Parse(_connCount.ToString()) < int.Parse(txtConns.Text))
{
//锁定连接数计时器+1
lock (_connCount)
{
_connCount = int.Parse(_connCount.ToString()) + 1;
if (int.Parse(_connCount.ToString()) > int.Parse(txtConns.Text))
break;
}
IDatabase db = DatabaseFactory.CreateDatabase(DatabaseType.SqlServer, connStr);
//抽签,go<=10,模拟1个用户新增一条数据
// go>10<=20,模拟1个用户随机更新一条数据
// go>=20,模拟1个用户随机删除一条数据
Thread.Sleep(100);
go = new Random().Next(1, 30);
//新增记录
if (go <= 10 || _DocNos.Count < 1)
{
cmd = db.CreateCommand(SQL);
cmd.AddParam("@QONO", GetDocNo());
cmd.AddParam("@DocDate", DateTime.Now);
cmd.AddParam("@CustomerCode", DateTime.Now.ToString("yyyyMMddHHmmssfff"));
cmd.AddParam("@RefPONO", DateTime.Now.ToString("yyyyMMddHHmmssfff"));
cmd.AddParam("@Currency", "RMB");
cmd.AddParam("@Sales", "admin");
cmd.AddParam("@CreationDate", DateTime.Now);
cmd.AddParam("@CreatedBy", "admin");
cmd.AddParam("@LastUpdatedBy", "admin");
cmd.AddParam("@LastUpdateDate", DateTime.Now);
int i = db.ExecuteCommand(cmd.Command);
if (i > 0)
{
//执行命令:处理的记录数
lock (_Rows_Inserted)
{
_Rows_Inserted = int.Parse(_Rows_Inserted.ToString()) + 1;
}
}
}
//修改记录
if (go > 10 && go <= 20)
{
cmd = db.CreateCommand(SQL1);
cmd.AddParam("@QONO", GetDocNoExists());
cmd.AddParam("@Client", "csframework.com");
cmd.AddParam("@Remark", "用户更新了数据");
cmd.AddParam("@LastUpdateDate", DateTime.Now);
int i = db.ExecuteCommand(cmd.Command);
//执行命令:处理的记录数
lock (_Rows_Updated)
{
_Rows_Updated = int.Parse(_Rows_Updated.ToString()) + 1;
}
}
//删除记录
if (go > 20 && go <= 30)
{
cmd = db.CreateCommand(SQL2);
cmd.AddParam("@QONO", GetDocNoExists());
//执行命令:处理的记录数
int i = db.ExecuteCommand(cmd.Command);
lock (_Rows_Deleted)
{
_Rows_Deleted = int.Parse(_Rows_Deleted.ToString()) + 1;//仅统计删除成功的记录
}
}
sub_total++;
if (cmd != null) cmd.Command.Dispose();
db = null;
//通知处理1次
this.Invoke(new SyncCall(this.OnProgress), new object[] { 1 });
}
lock (_threadList) _threadList.Remove(currentID);
lock (_ThreadFinish) _ThreadFinish = int.Parse(_ThreadFinish.ToString()) + 1;
//通知事件:线程处理完成
this.Invoke(new SyncCall(this.OnResult), new object[] { $"线程<{currentID}>结束,共处理:{sub_total}个SQL连接!" });
Application.DoEvents();
}
catch (Exception ex)
{
this.Invoke(new SyncCall(this.OnResult), new object[] { "错误:" + ex.Message });
lock (_ThreadFinish) _ThreadFinish = int.Parse(_ThreadFinish.ToString()) + 1;
lock (_Failed) _Failed = int.Parse(_Failed.ToString()) + 1;
}
}
private string GetDocNoExists()
{
lock (_DocNos)
{
int i = new Random().Next(1, _DocNos.Count);
return _DocNos[i - 1];
}
}
///
/// 初始化进度条
///
private void DoPrepareProgress()
{
lblProgress.Text = "0/0";
pb.Minimum = 0;
pb.Maximum = int.Parse(txtConns.Text);
pb.Value = 0;
}
///
/// 获取单据号码
///
///
private string GetDocNo()
{
Thread.Sleep(5);
var docNo = DateTime.Now.ToString("yyyyMMddHHmmssfff") + Guid.NewGuid().ToString().ToLower().Replace("-", "").Substring(0, 10);
lock (_DocNos)
{
_DocNos.Add(docNo);
}
return docNo;
}
///
/// 显示结果信息
///
///
private void OnResult(object value)
{
string text = value.ToString();
txtResult.AppendText(text + "\r\n");
txtResult.ScrollToCaret();
if (text.IndexOf("开始线程") >= 0)
txtRunThreads.Text = _threadCount.ToString();
}
///
/// 更新进度条
///
///
private void OnProgress(object value)
{
if (pb.Value + 1 <= pb.Maximum)
{
pb.Value++;
lblProgress.Text = pb.Value.ToString() + "/" + pb.Maximum.ToString();
TimeSpan ts = DateTime.Now - _startTime;
lblTime.Text = "用时:" + ts.TotalSeconds.ToString() + "秒.";
}
else
{
}
}
}
///
/// 异步调用过程
///
///
public delegate void SyncCall(object value);
}