c#實(shí)現(xiàn)用SQL池,多線程定時批量執(zhí)行SQL語句的方法
在實(shí)際項(xiàng)目開發(fā)中,業(yè)務(wù)邏輯層的處理速度往往很快,特別是在開發(fā)Socket通信服務(wù)的時候,網(wǎng)絡(luò)傳輸很快,但是一旦加上數(shù)據(jù)庫操作,性能一落千丈,數(shù)據(jù)庫操作的效率往往成為一個系統(tǒng)整體性能的瓶頸。面對這問題,我們怎么辦呢?好,下面我就為大家介紹一種方法:構(gòu)建SQL池,分離業(yè)務(wù)邏輯層和數(shù)據(jù)訪問層,讓業(yè)務(wù)邏輯層從低效的數(shù)據(jù)庫操作解脫,以提高系統(tǒng)整體性能。
(一)SQL池
SQL池是SQL容器,用于存放業(yè)務(wù)邏輯層拋過來的SQL語句。SQL池主要提供以下幾種方法:
1)internal string Pop(),從池中取出SQL。
2)internal void Push(string item),增加一個SQL到池中。
3)internal string[] Clear(),清空SQL池,清空前,返回SQL池中所有SQL語句。
特別提醒一下,SQL池是面向多線程的,所以必須對公共資源SQL采取鎖機(jī)制。這里采用互斥鎖,當(dāng)業(yè)務(wù)邏輯層線程往SQL池中拋入SQL語句時,禁止SQL執(zhí)行線程執(zhí)行SQL語句,反之,當(dāng)SQL執(zhí)行線程執(zhí)行SQL語句時,也不允許業(yè)務(wù)邏輯層線程往SQL池中拋入SQL語句。為什么要這么做?因?yàn)镾QL執(zhí)行線程是批量執(zhí)行SQL語句,在批量執(zhí)行SQL語句前,會從池中取出所有SQL語句,如果此時業(yè)務(wù)邏輯層線程往SQL池中拋入SQL語句,則會導(dǎo)致這些SQL語句丟失,得不到執(zhí)行。
下面是SQL池代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Test1
{
sealed class SQLPool
{
//互斥鎖
public static Mutex mutexSQLPool = new Mutex();
//SQL池
Stack<string> pool;
/// <summary>
/// 初始化SQL池
/// </summary>
internal SQLPool()
{
this.pool = new Stack<string>();
}
/// <summary>
/// 獲取SQL池?cái)?shù)量
/// </summary>
internal Int32 Count
{
get { return this.pool.Count; }
}
/// <summary>
/// 從池中取出SQL
/// </summary>
/// <returns></returns>
internal string Pop()
{
lock (this.pool)
{
return this.pool.Pop();
}
}
/// <summary>
/// 增加一個SQL到池中
/// </summary>
/// <param name="item"></param>
internal void Push(string item)
{
if (item.Trim() == "")
{
throw new ArgumentNullException("Items added to a SQLPool cannot be null");
}
//此處向SQL池中push SQL必須與Clear互斥
mutexSQLPool.WaitOne();
try
{
this.pool.Push(item); //此處如果出錯,則不會執(zhí)行ReleaseMutex,將會死鎖
}
catch
{
}
mutexSQLPool.ReleaseMutex();
}
/// <summary>
/// 清空SQL池
/// 清空前,返回SQL池中所有SQL語句,
/// </summary>
internal string[] Clear()
{
string[] array = new string[] { };
//此處必須與Push互斥
mutexSQLPool.WaitOne();
try
{
array = this.pool.ToArray(); //此處如果出錯,則不會執(zhí)行ReleaseMutex,將會死鎖
this.pool.Clear();
}
catch
{
}
mutexSQLPool.ReleaseMutex();
return array;
}
}
}
(二)SQL池管理
SQL池管理主要用于管理SQL池,向業(yè)務(wù)邏輯層線程和SQL執(zhí)行線程提供接口。
業(yè)務(wù)邏輯層線程調(diào)用 public void PushSQL(string strSQL) 方法,用于向SQL池拋入SQL語句。
SQL執(zhí)行線程調(diào)用 public void ExecuteSQL(object obj) 方法,用于批量執(zhí)行SQL池中的SQL語句。
注意,SQL池管理類采用單例模型,為什么要采用單例模型?因?yàn)镾QL池只能存在一個實(shí)例,無論是業(yè)務(wù)邏輯層線程還是SQL執(zhí)行線程,僅會操作這一個實(shí)例,否則,將會導(dǎo)致SQL池不唯一,SQL執(zhí)行無效。
下面是SQL池管理類代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test1
{
class SQLPoolManage
{
//單例模型
public static readonly SQLPoolManage sqlPoolManage = new SQLPoolManage();
#region 屬性
SQLPool poolOfSQL;
#endregion
#region 構(gòu)造函數(shù)
/// <summary>
/// 初始化
/// </summary>
public SQLPoolManage()
{
this.poolOfSQL = new SQLPool();
}
#endregion
#region 方法
/// <summary>
/// 將SQL語句加入SQL池中
/// </summary>
/// <param name="strSQL"></param>
public void PushSQL(string strSQL)
{
this.poolOfSQL.Push(strSQL);
}
/// <summary>
/// 每隔一段時間,觸發(fā)ExecuteSQL
/// ExecuteSQL用于執(zhí)行SQL池中的SQL語句
/// </summary>
/// <param name="obj"></param>
public void ExecuteSQL(object obj)
{
if (this.poolOfSQL.Count > 0)
{
string[] array = this.poolOfSQL.Clear();
//遍歷array,執(zhí)行SQL
for (int i = 0; i < array.Length; i++)
{
if (array[i].ToString().Trim() != "")
{
try
{
//數(shù)據(jù)庫操作
//......
}
catch
{
}
}
}
}
}
#endregion
}
}
(三)定時觸發(fā)SQL執(zhí)行線程
總結(jié)有以下三種方法:
方法一:調(diào)用線程執(zhí)行方法,在方法中實(shí)現(xiàn)死循環(huán),每個循環(huán)Sleep設(shè)定時間;
方法二:使用System.Timers.Timer類;
方法三:使用System.Threading.Timer;
代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Test1
{
class Program
{
static void Main(string[] args)
{
//向SQL池中拋入SQL語句
SQLPoolManage.sqlPoolManage.PushSQL("delete from tbl_test where id = 1");
//定時觸發(fā)SQL執(zhí)行線程
System.Threading.Timer threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null, 0, 100);
Console.ReadLine();
}
}
}
相關(guān)文章
C#實(shí)現(xiàn)根據(jù)實(shí)體類自動創(chuàng)建數(shù)據(jù)庫表
本文主要介紹了C#通過自定義特性實(shí)現(xiàn)根據(jù)實(shí)體類自動創(chuàng)建數(shù)據(jù)庫表的方法。具有很好的參考價值,需要的朋友一起來看下吧2016-12-12C#編程自學(xué)之?dāng)?shù)據(jù)類型和變量一
本節(jié)課我們將學(xué)習(xí)C#編程語言的數(shù)據(jù)類型,數(shù)據(jù)類型可以分為值類型和引用類型,接著介紹變量的使用方法和作用域等內(nèi)容,為了方便大家理解,我們還會舉一些小例子作為說明。2015-10-10DevExpress實(shí)現(xiàn)GridControl根據(jù)列選中一行
這篇文章主要介紹了DevExpress實(shí)現(xiàn)GridControl根據(jù)列選中一行,比較實(shí)用的功能,需要的朋友可以參考下2014-08-08C#多線程學(xué)習(xí)之Thread、ThreadPool、Task、Parallel四者區(qū)別
這篇文章主要以一些簡單的小例子,簡述多線程的發(fā)展歷程:Thread,ThreadPool,Task,Parallel。文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#多線程有一定幫助,需要的朋友可以參考一下2021-12-12Winform ComboBox如何獨(dú)立繪制下拉選項(xiàng)的字體顏色
這篇文章主要介紹了Winform ComboBox如何獨(dú)立繪制下拉選項(xiàng)的字體顏色,幫助大家更好的理解和使用c# winform,感興趣的朋友可以了解下2020-11-11