c#實(shí)現(xiàn)用SQL池,多線(xiàn)程定時(shí)批量執(zhí)行SQL語(yǔ)句的方法
在實(shí)際項(xiàng)目開(kāi)發(fā)中,業(yè)務(wù)邏輯層的處理速度往往很快,特別是在開(kāi)發(fā)Socket通信服務(wù)的時(shí)候,網(wǎng)絡(luò)傳輸很快,但是一旦加上數(shù)據(jù)庫(kù)操作,性能一落千丈,數(shù)據(jù)庫(kù)操作的效率往往成為一個(gè)系統(tǒng)整體性能的瓶頸。面對(duì)這問(wèn)題,我們?cè)趺崔k呢?好,下面我就為大家介紹一種方法:構(gòu)建SQL池,分離業(yè)務(wù)邏輯層和數(shù)據(jù)訪(fǎng)問(wèn)層,讓業(yè)務(wù)邏輯層從低效的數(shù)據(jù)庫(kù)操作解脫,以提高系統(tǒng)整體性能。
(一)SQL池
SQL池是SQL容器,用于存放業(yè)務(wù)邏輯層拋過(guò)來(lái)的SQL語(yǔ)句。SQL池主要提供以下幾種方法:
1)internal string Pop(),從池中取出SQL。
2)internal void Push(string item),增加一個(gè)SQL到池中。
3)internal string[] Clear(),清空SQL池,清空前,返回SQL池中所有SQL語(yǔ)句。
特別提醒一下,SQL池是面向多線(xiàn)程的,所以必須對(duì)公共資源SQL采取鎖機(jī)制。這里采用互斥鎖,當(dāng)業(yè)務(wù)邏輯層線(xiàn)程往SQL池中拋入SQL語(yǔ)句時(shí),禁止SQL執(zhí)行線(xiàn)程執(zhí)行SQL語(yǔ)句,反之,當(dāng)SQL執(zhí)行線(xiàn)程執(zhí)行SQL語(yǔ)句時(shí),也不允許業(yè)務(wù)邏輯層線(xiàn)程往SQL池中拋入SQL語(yǔ)句。為什么要這么做?因?yàn)镾QL執(zhí)行線(xiàn)程是批量執(zhí)行SQL語(yǔ)句,在批量執(zhí)行SQL語(yǔ)句前,會(huì)從池中取出所有SQL語(yǔ)句,如果此時(shí)業(yè)務(wù)邏輯層線(xiàn)程往SQL池中拋入SQL語(yǔ)句,則會(huì)導(dǎo)致這些SQL語(yǔ)句丟失,得不到執(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>
/// 增加一個(gè)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); //此處如果出錯(cuò),則不會(huì)執(zhí)行ReleaseMutex,將會(huì)死鎖
}
catch
{
}
mutexSQLPool.ReleaseMutex();
}
/// <summary>
/// 清空SQL池
/// 清空前,返回SQL池中所有SQL語(yǔ)句,
/// </summary>
internal string[] Clear()
{
string[] array = new string[] { };
//此處必須與Push互斥
mutexSQLPool.WaitOne();
try
{
array = this.pool.ToArray(); //此處如果出錯(cuò),則不會(huì)執(zhí)行ReleaseMutex,將會(huì)死鎖
this.pool.Clear();
}
catch
{
}
mutexSQLPool.ReleaseMutex();
return array;
}
}
}
(二)SQL池管理
SQL池管理主要用于管理SQL池,向業(yè)務(wù)邏輯層線(xiàn)程和SQL執(zhí)行線(xiàn)程提供接口。
業(yè)務(wù)邏輯層線(xiàn)程調(diào)用 public void PushSQL(string strSQL) 方法,用于向SQL池拋入SQL語(yǔ)句。
SQL執(zhí)行線(xiàn)程調(diào)用 public void ExecuteSQL(object obj) 方法,用于批量執(zhí)行SQL池中的SQL語(yǔ)句。
注意,SQL池管理類(lèi)采用單例模型,為什么要采用單例模型?因?yàn)镾QL池只能存在一個(gè)實(shí)例,無(wú)論是業(yè)務(wù)邏輯層線(xiàn)程還是SQL執(zhí)行線(xiàn)程,僅會(huì)操作這一個(gè)實(shí)例,否則,將會(huì)導(dǎo)致SQL池不唯一,SQL執(zhí)行無(wú)效。
下面是SQL池管理類(lèi)代碼:
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語(yǔ)句加入SQL池中
/// </summary>
/// <param name="strSQL"></param>
public void PushSQL(string strSQL)
{
this.poolOfSQL.Push(strSQL);
}
/// <summary>
/// 每隔一段時(shí)間,觸發(fā)ExecuteSQL
/// ExecuteSQL用于執(zhí)行SQL池中的SQL語(yǔ)句
/// </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ù)庫(kù)操作
//......
}
catch
{
}
}
}
}
}
#endregion
}
}
(三)定時(shí)觸發(fā)SQL執(zhí)行線(xiàn)程
總結(jié)有以下三種方法:
方法一:調(diào)用線(xiàn)程執(zhí)行方法,在方法中實(shí)現(xiàn)死循環(huán),每個(gè)循環(huán)Sleep設(shè)定時(shí)間;
方法二:使用System.Timers.Timer類(lèi);
方法三:使用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語(yǔ)句
SQLPoolManage.sqlPoolManage.PushSQL("delete from tbl_test where id = 1");
//定時(shí)觸發(fā)SQL執(zhí)行線(xiàn)程
System.Threading.Timer threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null, 0, 100);
Console.ReadLine();
}
}
}
相關(guān)文章
C#異步迭代IAsyncEnumerable應(yīng)用實(shí)現(xiàn)
IAsyncEnumerable可以來(lái)實(shí)現(xiàn)異步迭代,本文就主要介紹了C#異步迭代IAsyncEnumerable應(yīng)用實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
Unity編輯器資源導(dǎo)入處理函數(shù)OnPostprocessTexture實(shí)例深入解析
這篇文章主要為大家介紹了Unity編輯器資源導(dǎo)入處理函數(shù)OnPostprocessTexture實(shí)例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
C#實(shí)現(xiàn)文件與Base64的相互轉(zhuǎn)換
本文主要介紹了C#實(shí)現(xiàn)文件與Base64的相互轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06

