c#實現用SQL池(多執行緒),定時批量執行SQL語句 (轉)
(一)SQL池
SQL池是SQL容器,用於存放業務邏輯層拋過來的SQL語句。SQL池主要提供以下幾種方法:
1)internal string Pop(),從池中取出SQL。
2)internal void Push(string item),增加一個SQL到池中。
3)internal string[] Clear(),清空SQL池,清空前,返回SQL池中所有SQL語句。
特別提醒一下,SQL池是面向多執行緒的,所以必須對公共資源SQL採取鎖機制。這裡採用互斥鎖,當業務邏輯層執行緒往SQL池中拋入SQL語句時,禁止SQL執行執行緒執行SQL語句,反之,當SQL執行執行緒執行SQL語句時,也不允許業務邏輯層執行緒往SQL池中拋入SQL語句。為什麼要這麼做?因為SQL執行執行緒是批量執行SQL語句,在批量執行SQL語句前,會從池中取出所有SQL語句,如果此時業務邏輯層執行緒往SQL池中拋入SQL語句,則會導致這些SQL語句丟失,得不到執行。
下面是SQL池程式碼:
01 |
using System; |
02 |
using System.Collections.Generic; |
03 |
using System.Linq; |
04 |
using System.Text; |
05 |
using System.Threading; |
06 |
07 |
namespace Test1 |
08 |
{ |
09 |
sealed class SQLPool |
10 |
{ |
11 |
//互斥鎖 |
12 |
public static Mutex
mutexSQLPool = new Mutex(); |
13 |
14 |
//SQL池 |
15 |
Stack< string >
pool; |
16 |
17 |
/// <summary> |
18 |
/// 初始化SQL池 |
19 |
/// </summary> |
20 |
internal SQLPool() |
21 |
{ |
22 |
this .pool
= new Stack< string >(); |
23 |
} |
24 |
25 |
26 |
/// <summary> |
27 |
/// 獲取SQL池數量 |
28 |
/// </summary> |
29 |
internal Int32
Count |
30 |
{ |
31 |
get { return this .pool.Count;
} |
32 |
} |
33 |
34 |
35 |
/// <summary> |
36 |
/// 從池中取出SQL |
37 |
/// </summary> |
38 |
/// <returns></returns> |
39 |
internal string Pop() |
40 |
{ |
41 |
lock ( this .pool) |
42 |
{ |
43 |
return this .pool.Pop(); |
44 |
} |
45 |
} |
46 |
47 |
48 |
/// <summary> |
49 |
/// 增加一個SQL到池中 |
50 |
/// </summary> |
51 |
/// <param name="item"></param> |
52 |
internal void Push( string item) |
53 |
{ |
54 |
if (item.Trim()
== "" ) |
55 |
{ |
56 |
throw new ArgumentNullException( "Items
added to a SQLPool cannot be null" ); |
57 |
} |
58 |
59 |
//此處向SQL池中push SQL必須與Clear互斥 |
60 |
mutexSQLPool.WaitOne(); |
61 |
try |
62 |
{ |
63 |
this .pool.Push(item); //此處如果出錯,則不會執行ReleaseMutex,將會死鎖 |
64 |
} |
65 |
catch |
66 |
{ |
67 |
} |
68 |
mutexSQLPool.ReleaseMutex(); |
69 |
} |
70 |
71 |
72 |
/// <summary> |
73 |
/// 清空SQL池 |
74 |
/// 清空前,返回SQL池中所有SQL語句, |
75 |
/// </summary> |
76 |
internal string []
Clear() |
77 |
{ |
78 |
string []
array = new string []
{ }; |
79 |
80 |
//此處必須與Push互斥 |
81 |
mutexSQLPool.WaitOne(); |
82 |
try |
83 |
{ |
84 |
array = this .pool.ToArray(); //此處如果出錯,則不會執行ReleaseMutex,將會死鎖 |
85 |
this .pool.Clear(); |
86 |
} |
87 |
catch |
88 |
{ |
89 |
} |
90 |
mutexSQLPool.ReleaseMutex(); |
91 |
92 |
return array; |
93 |
} |
94 |
} |
95 |
} |
(二)SQL池管理
SQL池管理主要用於管理SQL池,向業務邏輯層執行緒和SQL執行執行緒提供介面。
業務邏輯層執行緒呼叫 public void PushSQL(string strSQL) 方法,用於向SQL池拋入SQL語句。
SQL執行執行緒呼叫 public void ExecuteSQL(object obj) 方法,用於批量執行SQL池中的SQL語句。
注意,SQL池管理類採用單例模型,為什麼要採用單例模型?因為SQL池只能存在一個例項,無論是業務邏輯層執行緒還是SQL執行執行緒,僅會操作這一個例項,否則,將會導致SQL池不唯一,SQL執行無效。
下面是SQL池管理類程式碼:
01 |
using System; |
02 |
using System.Collections.Generic; |
03 |
using System.Linq; |
04 |
using System.Text; |
05 |
06 |
namespace Test1 |
07 |
{ |
08 |
class SQLPoolManage |
09 |
{ |
10 |
//單例模型 |
11 |
public static readonly SQLPoolManage
sqlPoolManage = new SQLPoolManage(); |
12 |
13 |
#region 屬性 |
14 |
SQLPool poolOfSQL; |
15 |
#endregion |
16 |
17 |
18 |
#region 建構函式 |
19 |
/// <summary> |
20 |
/// 初始化 |
21 |
/// </summary> |
22 |
public SQLPoolManage() |
23 |
{ |
24 |
this .poolOfSQL
= new SQLPool(); |
25 |
} |
26 |
#endregion |
27 |
28 |
29 |
#region 方法 |
30 |
/// <summary> |
31 |
/// 將SQL語句加入SQL池中 |
32 |
/// </summary> |
33 |
/// <param name="strSQL"></param> |
34 |
public void PushSQL( string strSQL) |
35 |
{ |
36 |
this .poolOfSQL.Push(strSQL); |
37 |
} |
38 |
39 |
40 |
/// <summary> |
41 |
/// 每隔一段時間,觸發ExecuteSQL |
42 |
/// ExecuteSQL用於執行SQL池中的SQL語句 |
43 |
/// </summary> |
44 |
/// <param name="obj"></param> |
45 |
public void ExecuteSQL( object obj) |
46 |
{ |
47 |
if ( this .poolOfSQL.Count
> 0) |
48 |
{ |
49 |
string []
array = this .poolOfSQL.Clear(); |
50 |
//遍歷array,執行SQL |
51 |
for ( int i
= 0; i < array.Length; i++) |
52 |
{ |
53 |
if (array[i].ToString().Trim()
!= "" ) |
54 |
{ |
55 |
try |
56 |
{ |
57 |
//資料庫操作 |
58 |
//...... |
59 |
} |
60 |
catch |
61 |
{ |
62 |
} |
63 |
} |
64 |
} |
65 |
} |
66 |
} |
67 |
#endregion |
68 |
69 |
} |
70 |
} |
(三)定時觸發SQL執行執行緒
方法一:呼叫執行緒執行方法,在方法中實現死迴圈,每個迴圈Sleep設定時間;
方法二:使用System.Timers.Timer類;
方法三:使用System.Threading.Timer;
程式碼如下:
01 |
using System; |
02 |
using System.Collections.Generic; |
03 |
using System.Linq; |
04 |
using System.Text; |
05 |
06 |
using System.Threading; |
07 |
08 |
namespace Test1 |
09 |
{ |
10 |
11 |
class Program |
12 |
{ |
13 |
static void Main( string []
args) |
14 |
{ |
15 |
//向SQL池中拋入SQL語句 |
16 |
SQLPoolManage.sqlPoolManage.PushSQL( "delete
from tbl_test where id = 1" ); |
17 |
18 |
//定時觸發SQL執行執行緒 |
19 |
System.Threading.Timer threadTimer = new System.Threading.Timer( new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null ,
0, 100); |
20 |
21 |
Console.ReadLine(); |
22 |
} |
23 |
} |
24 |
} |