| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2829 人关注过本帖, 2 人收藏
标题:c#实现用SQL池(多线程),定时批量执行SQL语句
只看楼主 加入收藏
bygg
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:乖乖的心中
等 级:版主
威 望:241
帖 子:13555
专家分:3076
注 册:2006-10-23
结帖率:93.75%
收藏(2)
 问题点数:0 回复次数:13 
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执行线程
  总结有以下三种方法,具体请参见http://
方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间;
方法二:使用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, 0, 100);  

            Console.ReadLine(); 
        } 
    } 
}

《转自独上高楼》
搜索更多相关主题的帖子: SQL 线程 语句 批量 
2010-09-27 16:29
gameohyes
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:湖南
等 级:版主
威 望:53
帖 子:1275
专家分:3629
注 册:2009-3-5
收藏
得分:0 
支持

C#超级群 74862681,欢迎大家的到来!
2010-09-27 19:58
zhoufeng1988
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:北京
等 级:贵宾
威 望:27
帖 子:1432
专家分:6329
注 册:2009-5-31
收藏
得分:0 
感谢BBYY哥,受益匪浅。
2010-09-28 09:18
c1_wangyf
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:7
帖 子:665
专家分:2832
注 册:2010-5-24
收藏
得分:0 
支持!!
2010-09-28 09:24
bygg
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:乖乖的心中
等 级:版主
威 望:241
帖 子:13555
专家分:3076
注 册:2006-10-23
收藏
得分:0 
呵呵,近期我会将我看到的一些较好的文章整理或者转裁过来,让大家都了解了解。

飘过~~
2010-09-28 11:28
misswang
Rank: 8Rank: 8
来 自:湖北荆州
等 级:贵宾
威 望:15
帖 子:265
专家分:720
注 册:2010-3-11
收藏
得分:0 
程哥,这个不错...顶下

misswp2010@
wangping103@
2010-11-05 15:06
wangnannan
Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18
等 级:贵宾
威 望:87
帖 子:2546
专家分:9359
注 册:2007-11-3
收藏
得分:0 
学习 学习

出来混,谁不都要拼命的嘛。 。拼不赢?那就看谁倒霉了。 。有机会也要看谁下手快,快的就能赢,慢。 。狗屎你都抢不到。 。还说什么拼命?
2010-11-05 15:43
jalonlovesja
Rank: 5Rank: 5
来 自:湖南邵阳
等 级:职业侠客
帖 子:292
专家分:371
注 册:2008-2-19
收藏
得分:0 
好东西,谢谢LZ的分享啊!支持!!!!

小弟,身高1.60米,农村户口,小学文化,家有农田1亩.
2010-11-05 21:51
guang
Rank: 4
来 自:广东深圳
等 级:贵宾
威 望:13
帖 子:1414
专家分:285
注 册:2006-4-3
收藏
得分:0 
不错,不过需要返回值的话就不能这样做了

不相信未作牺牲竟先可拥有,只相信靠双手找到我的欲求!!
我的博客:http://liao5930.blog.
2010-11-06 18:03
quanshui
Rank: 1
等 级:新手上路
帖 子:29
专家分:0
注 册:2004-11-17
收藏
得分:0 
感谢BBYY哥,受益匪浅
2010-11-07 13:16
快速回复:c#实现用SQL池(多线程),定时批量执行SQL语句
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.039570 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved