在做一个小系统的时候,我想数据量交互不大,就都用一个链接执行算了,还能节省点资源,但是实际情况遇到了如下问题,在使用的过程中,有些数据操作会被转移到其他线程,这样;我这个简单的想法遇到了问题,因为一个现场在使用这个链接的时候,其他线程也会同步插入执行数据操作,这样一个链接就会面临共用的冲突,怎么办呢,有如下三种方案:
1.1.数据两次一次一联,一用,一释放。
1.2.强制是数据库的执行放到一个现场,那么得把所有的执行参数放到队列中,有数据支持的线程按照队列的顺序执行。也可以在使用的时候把链接索起来。这样强制的使数据的处理串行。
1.3.做一个内部的链接对象使用池,池中的对象可供服用,解决重复链接的问题,提供多个对象解决现场使用冲突的问题。
我选择了方案三,做了如下实验,记录如下
2.1 确认数据链接状态,使用完的数据链接是什么状态呢?
2.1.1 目的:我想根据链接的状态判断链接是在使用中,还是可以给别人使用;就是在可以使用的情况下,我就用该链接执行,否则使用或者创建其他的链接。
代码。
- using System;
- using System.Data;
-
- namespace 数据库链接状态确认
- {
- /// <summary>
- /// 确认数据库通常执行完成是什么状态
- /// </summary>
- public class Test1:Singleton<Test1>
- {
- public void main()
- {
- test1();
- }
- private void test1()
- {
- DBmsqlSub dBmsqlSub = new DBmsqlSub();
- string sql = "insert into tb1(v1) values(2)";
- dBmsqlSub.ExecuteNonQuery(sql);
- ConnectionState connectionState = dBmsqlSub.getState();
- Console.WriteLine(connectionState);
- dBmsqlSub.Close();
- }
- }
- }
结果,整理使用后的链接状态是open,那是不是open的时候就可以供别人使用了呢,要是在执行的时候也是open状态,那我就没有判定已经了。
- 数据库链接状态确认
- id0
- index:1 isuser:False setuser:False
- Open
2.2 数据库在执行的时候,是不是有一个执行中的状态呢?
代码
- using System;
- using System.Threading.Tasks;
-
- namespace 数据库链接状态确认
- {
- /// <summary>
- /// 目的:确认执行中的数据状态
- /// </summary>
- class Test2:Singleton<Test2>
- {
- public void main() {
- DBmsqlSub dBmsqlSub = new DBmsqlSub();
- Task.Factory.StartNew(test2Exe, (Object)dBmsqlSub);
- Task.Factory.StartNew(test2Exe, (Object)dBmsqlSub);
- Task.Factory.StartNew(test2State, dBmsqlSub);
- }
- private void test2Exe(object dBmsqlSub)
- {
- int index = 1;
- while (true)
- {
- index++;
- string sql = "insert into tb1(v1) values(" + index + ")";
- ((DBmsqlSub)dBmsqlSub).ExecuteNonQuery(sql);
- Task.Delay(200);
- }
- }
- private void test2State(object dBmsqlSub)
- {
- while (true)
- {
- Console.WriteLine(((DBmsqlSub)dBmsqlSub).getState());
- }
- }
- }
- }
行结果执:即使执行中,对象的链接状态依然是open,那么用链接状态作为链接是否可用的计划泡汤了,那就只能用自添加的对象来控制链接是否可用了。
- Open
- Open
- Open
- Open
- id0
- Open
- Open
- Open
- Open
- Open
- Open
2.3 测试3:添加对象的状态,控制链接是否可用
2.3.1 代码
- using MySqlConnector;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace 数据库链接状态确认
- {
- class Test3:Singleton<Test3>
- {
- public void main() {
- test1();
- //test1();
- }
- private void test1() {
- Task.Factory.StartNew(test2Exe);
- Task.Factory.StartNew(test2Exe);
- Task.Factory.StartNew(test2Exe);
- }
- private void test2Exe()
- {
- int index = 1;
- while (true)
- {
- index++;
- string sql = "insert into tb1(v1) values(" + index + ")";
- DBmsql.getMy().ExecuteNonQuery(sql);
- }
- }
-
- private object MySqlDataReader(DBmsqlSub dBmsqlSub)
- {
- throw new NotImplementedException();
- }
-
- private void test2State(object dBmsqlSub)
- {
- while (true)
- {
- Console.WriteLine(((DBmsqlSub)dBmsqlSub).getState());
- }
- }
- }
- }
2.3.2
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace 数据库链接状态确认
- {
- class DBmsql : Singleton<DBmsql>
- {
- List<DBmsqlSub> dBmsqlSubs = new List<DBmsqlSub>();
- /// <summary>
- /// 执行sql命令
- /// </summary>
- /// <param name="CommandText"></param>
- public void ExecuteNonQuery(String CommandText)
- {
- getDBmsqlSub().ExecuteNonQuery(CommandText);
- }
-
- /// <summary>
- /// 插入数据,并返回插入数据的id
- /// </summary>
- /// <param name="CommandText"></param>
- /// <returns></returns>
- public int insertReturn(string CommandText)
- {
- int ret = getDBmsqlSub().insertReturn(CommandText);
- return ret;
- }
- /// <summary>
- /// 执行并返回一个对象
- /// </summary>
- /// <param name="CommandText"></param>
- /// <returns></returns>
- public object ExecuteScalar(string CommandText)
- {
- object o = getDBmsqlSub().ExecuteScalar(CommandText);
- return o;
- }
- /// <summary>
- /// 获取数据处理对象
- /// </summary>
- /// <returns></returns>
- private DBmsqlSub getDBmsqlSub()
- {
- DBmsqlSub ret = null;
-
- lock (dBmsqlSubs)
- {
- //避免两个同时取到允许的状态
- foreach (DBmsqlSub dBmsqlSub in dBmsqlSubs)
- {
- if (!dBmsqlSub.IsUrse())
- {
- ret = dBmsqlSub;
- dBmsqlSub.setIsUser(true);
- Console.WriteLine("get:" + ret.id);
- break;
- }
- }
- //避免两个同时创建对象,产生结果列表的错误
- if (ret == null&& dBmsqlSubs.Count<90)
- {
- DBmsqlSub dBmsqlSub = new DBmsqlSub();
- dBmsqlSubs.Add(dBmsqlSub);
- dBmsqlSub.setIsUser(true);
- ret = dBmsqlSub;
- Console.WriteLine("get:" + ret.id);
- }
- }
- return ret;
- }
- }
- }
2.3.3
- using MySqlConnector;
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace 数据库链接状态确认
- {
- public class Constand {
- public static string mesConnStr = "server=localhost;port=3306;database=db1;user id=root;password=123456;Charset=utf8;";
- }
- class DBmsqlSub
- {
- static int index = 0;
- public int id = 0;
- private bool isUser = false;
- private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
- MySqlConnection mConn;
- MySqlCommand mCmd;
- public void setIsUser(bool value) {
- lock (this) {
- Console.WriteLine("index:" + index + " isuser:" + isUser+" setuser:"+ value);
- isUser = value;
- }
- }
-
- public MySqlDataReader MySqlDataReader { get; private set; }
-
- public DBmsqlSub()
- {
- id = index++;
- try
- {
- mConn = new MySqlConnection(Constand.mesConnStr);
- mConn.Open();
- mCmd = new MySqlCommand();
- mCmd.Connection = mConn;
- }
- catch (Exception e)
- {
- logger.Error(e.ToString());
- }
- }
- ~DBmsqlSub()
- {
- mConn.Close();
- }
- public void Close()
- {
- mConn.Close();
- }
- public bool isOpen()
- {
- if (mConn.State == ConnectionState.Closed)
- {
- mConn.Open();
- }
- if (mConn.State == ConnectionState.Open)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- public MySqlCommand getCmd()
- {
- return mCmd;
- }
- /// <summary>
- /// 如果没有链接,就直接链接
- /// </summary>
- private void conn()
- {
- if (mConn.State != ConnectionState.Open)
- {
- mConn.Open();
- }
- }
-
- /// <summary>
- /// 执行sql命令
- /// </summary>
- /// <param name="CommandText"></param>
- public void ExecuteNonQuery(String CommandText)
- {
- //setIsUser(true);
- mCmd.CommandText = CommandText;
- try
- {
- Console.WriteLine("id"+id);
- mCmd.ExecuteNonQuery();
- }
- catch (Exception ex)
- {
- logger.Error(ex.ToString());
- }
- finally {
- setIsUser(false);
- }
- }
-
- /// <summary>
- /// 插入数据,并返回插入数据的id
- /// </summary>
- /// <param name="CommandText"></param>
- /// <returns></returns>
- public int insertReturn(string CommandText)
- {
- setIsUser(true);
- int ret = 0;
- MySqlTransaction sqlTransaction = mConn.BeginTransaction();
- try
- {
- mCmd.CommandText = CommandText;
- object o = mCmd.ExecuteScalar();
- sqlTransaction.Commit();
- ret = int.Parse(o.ToString());
- }
- catch (Exception e)
- {
- logger.Error(e.ToString());
- sqlTransaction.Rollback();
- }
- finally
- {
- setIsUser(false);
- }
- return ret;
- }
- /// <summary>
- /// 执行并返回一个对象
- /// </summary>
- /// <param name="CommandText"></param>
- /// <returns></returns>
- public object ExecuteScalar(string CommandText)
- {
- setIsUser(true);
- object o = null;
- mCmd.CommandText = CommandText;
- try
- {
- o = mCmd.ExecuteScalar();
- }
- catch (Exception ex)
- {
- logger.Error(ex.ToString());
- }
- finally
- {
- setIsUser(false);
- }
- return o;
- }
- public MySqlDataReader ExecuteReader(string CommandText)
- {
- setIsUser(true);
- MySqlDataReader mySqlDataReader = null;
- mCmd.CommandText = CommandText;
- try
- {
- mySqlDataReader = mCmd.ExecuteReader();
- //mConn.Close();
- }
- catch (Exception ex)
- {
- logger.Error(ex.ToString());
- }
- finally
- {
- setIsUser(false);
- }
- return mySqlDataReader;
- }
- public ConnectionState getState() {
- return mConn.State;
- }
- public bool IsUrse() {
- return isUser;
- }
- }
- }
2.3.4
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace 数据库链接状态确认
- {
- /// <summary>
- /// 单件构象基类
- /// </summary>
- /// <typeparam name="T"></typeparam>
- public class Singleton<T> where T : new()
- {
- static T t = default(T);
- public static T getMy()
- {
- if (t == null)
- {
- t = new T();
- }
- return t;
- }
- }
- }
运行结果:可用看出是几个链接对象在被循环的使用,也基本达到了直接的初衷,用尽可能少的链接,完成多线程的调用情景。
- id2
- index:5 isuser:True setuser:False
- index:5 isuser:False setuser:True
- index:5 isuser:True setuser:False
- get:3
- id3
- index:5 isuser:False setuser:True
- get:4
- id4
- index:5 isuser:True setuser:False
- index:5 isuser:False setuser:True
- get:2
- id2
- index:5 isuser:True setuser:False
- index:5 isuser:False setuser:True
- get:3
- id3