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执行线程

总结有以下三种方法:
方法一:调用线程执行方法,在方法中实现死循环,每个循环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();
        }
    }
}

(0)

相关推荐

  • C#访问SQL Server数据库的实现方法

    本文实例讲述了C#访问SQL Server数据库的实现方法.分享给大家供大家参考.具体如下: 这里介绍一下用C#访问SQL Server数据库.这里要涉及到几个类:SqlConnection类.SqlCommand类.SqlDataReader类. SqlConnection类用于建立与数据库的连接,SqlCommand类用于创建SQL命令,SqlDataReader对象是执行SqlCommand对象返回结果集的查询语句后的结果. 下面是部分代码: /*其中server表示服务器,"."

  • C#访问SQLServer增删改查代码实例

    一个专门实现访问sql server数据库增删改查的操作代码,分享给大家,具体内容如下 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; usi

  • C#基于SQLiteHelper类似SqlHelper类实现存取Sqlite数据库的方法

    本文实例讲述了C#基于SQLiteHelper类似SqlHelper类实现存取Sqlite数据库的方法.分享给大家供大家参考.具体如下: 这个类不是我实现的,英文原文地址为http://www.eggheadcafe.com/articles/20050315.asp,这里修改了原文中分析sql语句参数的方法,将方法名修改为AttachParameters,将其修饰符修改为private,并直接传递command到这个方法,直接绑定参数到comand.修改后的代码如下 using System;

  • C#实现过滤sql特殊字符的方法集合

    本文实例讲述了C#实现过滤sql特殊字符的方法集合.分享给大家供大家参考,具体如下: 1. /// <summary> /// 过滤不安全的字符串 /// </summary> /// <param name="Str"></param> /// <returns></returns> public static string FilteSQLStr(string Str) { Str = Str.Replace(

  • C#实现SQL批量插入数据到表的方法

    本文实例讲述了C#实现SQL批量插入数据到表的方法.分享给大家供大家参考,具体如下: #region 帮助实例:SQL 批量插入数据 多种方法 /// <summary> /// SqlBulkCopy往数据库中批量插入数据 /// </summary> /// <param name="sourceDataTable">数据源表</param> /// <param name="targetTableName"

  • C#中调用MySQL存储过程的方法

    本文实例讲述了C#中调用MySQL存储过程的方法.分享给大家供大家参考.具体如下: 这段代码演示在 C# 程序中调用 MySQL 的存储过程,没有返回值,没有参数传递. MySqlConnection myConnection; myConnection = new MySqlConnection(); myConnection.ConnectionString = "database="+database+";server="+ server+";use

  • C#/.Net 中快速批量给SQLite数据库插入测试数据

    使用transaction: var stopwatch = new Stopwatch(); using (var cmd = new SQLiteCommand(db_con)) using (var transaction = db_con.BeginTransaction()) { stopwatch.Reset(); stopwatch.Start(); foreach (var item in sorted) { sql = string.Format("insert into db

  • C#创建数据库及导入sql脚本的方法

    本文实例讲述了C#创建数据库及导入sql脚本的方法.分享给大家供大家参考,具体如下: C#创建数据库: /// <summary> /// 创建数据库 /// </summary> /// <param name="connStr">连接字符串</param> /// <param name="_strDBName">数据库名称</param> /// <returns></r

  • C#批量更新sql实例

    本文实例讲述了C#批量更新sql的方法,分享给大家供大家参考.具体方法如下: 要实现批量更新Card数据,主要有以下步骤: 1.首先建立数据库连接 2.把部分数据填充到Dataset中 3.修改Dataset中数据的值 4.更新Dataset 5.循环操作,具体操作过程见下面代码: 复制代码 代码如下: public void BatchUpdate(List<Card> list) {     using (SqlConnection conn = new SqlConnection(DbH

  • C#使用SqlBulkCopy批量复制数据到数据表

    本文实例讲述了C#使用SqlBulkCopy批量复制数据到数据表的方法.分享给大家供大家参考.具体实现方法如下: 使用 SqlBulkCopy 类只能向 SQL Server 表写入数据.但是,数据源不限于 SQL Server:可以使用任何数据源,只要数据可加载到 DataTable 实例或可使用 IDataReader 实例读取数据 1.使用Datatable作为数据源的方式: 下面的代码使用到了ColumnMappings,因为目标表和数据源Datatable的结构不一致,需要这么一个映射

随机推荐