c#实现用SQL池,多线程定时批量执行SQL语句的方法
在实际项目开发中,业务逻辑层的处理速度往往很快,特别是在开发Socket通信服务的时候,网络传输很快,但是一旦加上数据库操作,性能一落千丈,数据库操作的效率往往成为一个系统整体性能的瓶颈。面对这问题,我们怎么办呢?好,下面我就为大家介绍一种方法:构建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池代码: 复制代码 代码如下: 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池数量 /// </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); //此处如果出错,则不会执行ReleaseMutex,将会死锁 } catch { } mutexSQLPool.ReleaseMutex(); } /// <summary> /// 清空SQL池 /// 清空前,返回SQL池中所有SQL语句, /// </summary> internal string[] Clear() { string[] array = new string[] { }; //此处必须与Push互斥 mutexSQLPool.WaitOne(); try { array = this.pool.ToArray(); //此处如果出错,则不会执行ReleaseMutex,将会死锁 this.pool.Clear(); } catch { } mutexSQLPool.ReleaseMutex(); return array; } } } (二)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池管理类代码: 复制代码 代码如下: 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 构造函数 /// <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> /// 每隔一段时间,触发ExecuteSQL /// ExecuteSQL用于执行SQL池中的SQL语句 /// </summary> /// <param name="obj"></param> public void ExecuteSQL(object obj) { if (this.poolOfSQL.Count > 0) { string[] array = this.poolOfSQL.Clear(); //遍历array,执行SQL for (int i = 0; i < array.Length; i++) { if (array[i].ToString().Trim() != "") { try { //数据库操作 //...... } catch { } } } } } #endregion } } (三)定时触发SQL执行线程 总结有以下三种方法: 方法二:使用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"); //定时触发SQL执行线程 System.Threading.Timer threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL),null,100); Console.ReadLine(); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |