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
|
{
|
/// <summary>
|
/// C/S框架网,CSFramework.DB,C/S框架数据库并发测试
|
/// </summary>
|
public partial class frmSQLConcurrentTester : Form
|
{
|
|
static object _threadCount = 0;//线程数量
|
static object _connCount = 0;//已建立的SQL连接数
|
static List<object> _threadList = new List<object>();//线程数量
|
static DateTime _startTime = DateTime.Now;
|
|
static List<String> _DocNos = new List<string>();//本次测试生成的单据号码
|
|
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();//回收垃圾
|
}
|
|
/// <summary>
|
/// 等待线程
|
/// </summary>
|
private void WaitThreads()
|
{
|
while (int.Parse(_ThreadFinish.ToString()) < int.Parse(txtThreads.Text))
|
{
|
//处理线程....
|
Application.DoEvents();
|
}
|
}
|
|
/// <summary>
|
/// 启动一个线程
|
/// </summary>
|
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];
|
}
|
}
|
|
/// <summary>
|
/// 初始化进度条
|
/// </summary>
|
private void DoPrepareProgress()
|
{
|
lblProgress.Text = "0/0";
|
pb.Minimum = 0;
|
pb.Maximum = int.Parse(txtConns.Text);
|
pb.Value = 0;
|
}
|
|
/// <summary>
|
/// 获取单据号码
|
/// </summary>
|
/// <returns></returns>
|
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;
|
}
|
|
/// <summary>
|
/// 显示结果信息
|
/// </summary>
|
/// <param name="value"></param>
|
private void OnResult(object value)
|
{
|
string text = value.ToString();
|
txtResult.AppendText(text + "\r\n");
|
txtResult.ScrollToCaret();
|
|
if (text.IndexOf("开始线程") >= 0)
|
txtRunThreads.Text = _threadCount.ToString();
|
}
|
|
/// <summary>
|
/// 更新进度条
|
/// </summary>
|
/// <param name="value"></param>
|
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
|
{
|
|
}
|
}
|
}
|
|
/// <summary>
|
/// 异步调用过程
|
/// </summary>
|
/// <param name="value"></param>
|
public delegate void SyncCall(object value);
|
|
|
}
|