当前位置:   article > 正文

多线程并发读写MySql数据库可能出现脏读的问题_线程中insert数据 跳出线程无法查询

线程中insert数据 跳出线程无法查询

在多线程中使用同一mysql连接,一边读取数据库,一般修改数据库(insert,update,delete) 可能出现程序脏读的问题。

线程一:

delete from tb where ...

insert into tb... 

线程二:

select * from tb 

我们可以在查询中增加锁机制【lock in share mode】

select * from tb lock in share mode

共享锁 (lock in share mode)

允许不同事务之前共享加锁读取,但不允许其它事务修改或者加入排他锁
如果有修改必须等待一个事务提交完成,才可以执行,容易出现死锁

排他锁 (for update)

当一个事物加入排他锁后,不允许其他事务加共享锁或者排它锁读取,更加不允许其他事务修改加锁的行。

本文只是对共享锁进行测试

新建C#控制台应用程序MultiThreadMySqlDemo。

一、新建枚举DatabaseType

源程序如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace MultiThreadMySqlDemo
  6. {
  7. /// <summary>
  8. /// 数据库类型
  9. /// </summary>
  10. public enum DatabaseType
  11. {
  12. /// <summary>
  13. /// 微软SqlServer数据库
  14. /// </summary>
  15. SqlServer = 0,
  16. /// <summary>
  17. /// Oracle数据库
  18. /// </summary>
  19. Oracle = 1,
  20. /// <summary>
  21. /// MySql数据库
  22. /// </summary>
  23. MySql = 2,
  24. /// <summary>
  25. /// 轻量级SQLite数据库,多用于本地保存数据
  26. /// </summary>
  27. SQLite = 3,
  28. /// <summary>
  29. /// PostgreSql数据库
  30. /// </summary>
  31. PostgreSql = 4,
  32. /// <summary>
  33. /// IBM DB2数据
  34. /// </summary>
  35. DB2 = 5,
  36. /// <summary>
  37. /// IBM Informix数据库
  38. /// </summary>
  39. Informix = 6,
  40. /// <summary>
  41. /// 对象链接和嵌入数据库:如Access数据库
  42. /// </summary>
  43. OleDb = 7,
  44. /// <summary>
  45. /// 开放数据库互连:Open Database Connectivity
  46. /// </summary>
  47. ODBC = 8
  48. }
  49. }

二、数据库工厂类ProviderFactory

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Common;
  4. using System.Linq;
  5. using System.Text;
  6. namespace MultiThreadMySqlDemo
  7. {
  8. /// <summary>
  9. /// 数据库工厂,为不同类型的数据源类进行实例化
  10. /// </summary>
  11. public class ProviderFactory
  12. {
  13. private static Dictionary<DatabaseType, string> providerInvariantNames = new Dictionary<DatabaseType, string>();
  14. private static Dictionary<DatabaseType, DbProviderFactory> providerFactory = new Dictionary<DatabaseType, DbProviderFactory>();
  15. static ProviderFactory()
  16. {
  17. //加载已知的数据库访问类的程序集
  18. providerInvariantNames.Add(DatabaseType.SqlServer, "System.Data.SqlClient");
  19. providerInvariantNames.Add(DatabaseType.Oracle, "Oracle.DataAccess.Client");
  20. providerInvariantNames.Add(DatabaseType.MySql, "MySql.Data.MySqlClient");
  21. providerInvariantNames.Add(DatabaseType.SQLite, "System.Data.SQLite");
  22. providerInvariantNames.Add(DatabaseType.PostgreSql, "Npgsql");
  23. providerInvariantNames.Add(DatabaseType.DB2, "IBM.Data.DB2.iSeries");
  24. providerInvariantNames.Add(DatabaseType.Informix, "IBM.Data.Informix");
  25. providerInvariantNames.Add(DatabaseType.OleDb, "System.Data.OleDb");
  26. providerInvariantNames.Add(DatabaseType.ODBC, "System.Data.ODBC");
  27. }
  28. /// <summary>
  29. /// 获取指定数据库类型对应的程序集名称
  30. /// </summary>
  31. /// <param name="providerType"></param>
  32. /// <returns></returns>
  33. public static string GetProviderInvariantName(DatabaseType providerType)
  34. {
  35. return providerInvariantNames[providerType];
  36. }
  37. /// <summary>
  38. /// 获取指定类型的数据库对应的DbProviderFactory
  39. /// </summary>
  40. /// <param name="providerType"></param>
  41. /// <returns></returns>
  42. public static DbProviderFactory GetDbProviderFactory(DatabaseType providerType)
  43. {
  44. //如果还没有加载,则加载该DbProviderFactory
  45. if (!providerFactory.ContainsKey(providerType))
  46. {
  47. providerFactory.Add(providerType, ImportDbProviderFactory(providerType));
  48. }
  49. return providerFactory[providerType];
  50. }
  51. /// <summary>
  52. /// 加载指定数据库类型的DbProviderFactory
  53. /// </summary>
  54. /// <param name="providerType">数据库类型枚举</param>
  55. /// <returns></returns>
  56. private static DbProviderFactory ImportDbProviderFactory(DatabaseType providerType)
  57. {
  58. string providerName = providerInvariantNames[providerType];
  59. DbProviderFactory factory = null;
  60. try
  61. {
  62. //invariant 不变的,固定的 variant 变化的,不同的,变量
  63. //从全局程序集中查找,如果使用的dll(如:System.Data.SQLite.dll,该类库需要放在bin\debug目录下) 是32位的,则编译程序也要以32位(x86)运行
  64. //如果没有在App.config(或web.config)中配置节点:
  65. //<system.data><DbProviderFactories><add name="SQLite Data Provider".. /></DbProviderFactories></system.data>..,则需要更改对应的machine.config
  66. //32位(x86)的 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config
  67. //64位(x64)的 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config
  68. //<remove invariant = "System.Data.SQLite" /><add name = "SQLite Data Provider" invariant = "System.Data.SQLite" description = ".Net Framework Data Provider for SQLite" type = "System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
  69. factory = DbProviderFactories.GetFactory(providerName);
  70. }
  71. catch (Exception ex)
  72. {
  73. Console.WriteLine("加载程序集失败:" + providerName + "\n" + ex.Message, "指定的数据库对应的程序集无法加载");
  74. factory = null;
  75. }
  76. return factory;
  77. }
  78. }
  79. }

三、新建数据库操作类DbUtility

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Data;
  5. using System.Data.Common;
  6. using System.Reflection;
  7. using System.Text.RegularExpressions;
  8. namespace MultiThreadMySqlDemo
  9. {
  10. /// <summary>
  11. /// 通用数据库访问类,封装了对数据库的常见操作
  12. /// Author:斯内科
  13. /// </summary>
  14. public sealed class DbUtility
  15. {
  16. /// <summary>
  17. /// 定义一个静态变量来保存该类的实例
  18. /// </summary>
  19. private static DbUtility uniqueInstance;
  20. /// <summary>
  21. /// 锁对象
  22. /// </summary>
  23. private static object thisLock = new object();
  24. /// <summary>
  25. /// 数据库连接字符串
  26. /// </summary>
  27. public string ConnectionString { get; private set; }
  28. /// <summary>
  29. /// 数据库工厂,可以根据不同的数据库类型,实例化出对应的数据源类对象
  30. /// </summary>
  31. private DbProviderFactory providerFactory;
  32. /// <summary>
  33. /// 构造函数
  34. /// </summary>
  35. /// <param name="connectionString">数据库连接字符串</param>
  36. /// <param name="providerType">数据库类型枚举</param>
  37. public DbUtility(string connectionString, DatabaseType providerType)
  38. {
  39. ConnectionString = connectionString;
  40. providerFactory = ProviderFactory.GetDbProviderFactory(providerType);
  41. if (providerFactory == null)
  42. {
  43. throw new ArgumentException("Can't load DbProviderFactory for given value of providerType");
  44. }
  45. }
  46. /// <summary>
  47. /// 实例化该数据库访问类
  48. /// </summary>
  49. /// <param name="connectionString">数据库连接字符串</param>
  50. /// <param name="dbType">数据库类型字符串,如 SqlServer、Oracle</param>
  51. /// <returns></returns>
  52. public static DbUtility GetInstance(string connectionString, string dbType)
  53. {
  54. DatabaseType databaseType;
  55. bool parseResult = Enum.TryParse(dbType, true, out databaseType);
  56. if (!parseResult)
  57. {
  58. throw new Exception("不支持的数据库类型:" + dbType);
  59. }
  60. return GetInstance(connectionString, databaseType);
  61. }
  62. /// <summary>
  63. /// 实例化该数据库访问类
  64. /// </summary>
  65. /// <param name="connectionString">数据库连接字符串</param>
  66. /// <param name="databaseType">数据库类型枚举</param>
  67. /// <returns></returns>
  68. public static DbUtility GetInstance(string connectionString, DatabaseType databaseType)
  69. {
  70. // 如果类的实例不存在则创建,否则直接返回
  71. if (uniqueInstance == null)
  72. {
  73. lock (thisLock)
  74. {
  75. if (uniqueInstance == null)
  76. {
  77. uniqueInstance = new DbUtility(connectionString, databaseType);
  78. }
  79. }
  80. }
  81. return uniqueInstance;
  82. }
  83. /// <summary>
  84. /// 创建一个数据库命令对象
  85. /// </summary>
  86. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  87. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  88. /// <param name="commandType">命令字符串类型:Text为 SQL文本,StoredProcedure为 存储过程名</param>
  89. /// <returns></returns>
  90. public DbCommand CreateCommand(string sql, Dictionary<string, object> dict, CommandType commandType)
  91. {
  92. DbConnection connection = providerFactory.CreateConnection();
  93. connection.ConnectionString = ConnectionString;
  94. DbCommand command = CreateCommand(sql, dict, commandType, connection);
  95. return command;
  96. }
  97. /// <summary>
  98. /// 创建一个数据库命令对象
  99. /// </summary>
  100. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  101. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  102. /// <param name="commandType">命令字符串类型:Text为 SQL文本,StoredProcedure为 存储过程名</param>
  103. /// <param name="connection">数据库连接对象</param>
  104. /// <returns></returns>
  105. public DbCommand CreateCommand(string sql, Dictionary<string, object> dict, CommandType commandType, DbConnection connection)
  106. {
  107. DbCommand command = providerFactory.CreateCommand();
  108. command.Connection = connection;
  109. command.CommandType = commandType;
  110. command.CommandText = sql;
  111. if (dict != null)
  112. {
  113. foreach (string parameterName in dict.Keys)
  114. {
  115. DbParameter dbParameter = command.CreateParameter();
  116. dbParameter.ParameterName = parameterName;
  117. dbParameter.Value = dict[parameterName];
  118. command.Parameters.Add(dbParameter);
  119. }
  120. }
  121. return command;
  122. }
  123. /// <summary>
  124. /// 更新数据,执行增(insert into)、删(delete)、改(update)、创建表(create table)等操作
  125. /// </summary>
  126. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  127. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  128. /// <param name="commandType">命令字符串类型:Text(默认)为 SQL文本,StoredProcedure为 存储过程名</param>
  129. /// <returns></returns>
  130. public int UpdateData(string sql, Dictionary<string, object> dict, CommandType commandType = CommandType.Text)
  131. {
  132. int affectedRows = -1;
  133. using (DbCommand command = CreateCommand(sql, dict, commandType))
  134. {
  135. try
  136. {
  137. command.Connection.Open();
  138. affectedRows = command.ExecuteNonQuery();
  139. }
  140. catch (Exception ex)
  141. {
  142. Console.WriteLine(ex.Message, "更改数据时出现异常");
  143. }
  144. finally
  145. {
  146. command.Connection.Close();
  147. }
  148. }
  149. return affectedRows;
  150. }
  151. /// <summary>
  152. /// 事务处理
  153. /// </summary>
  154. /// <param name="sqlCollection">sql语句集合</param>
  155. /// <param name="dictCollection">每一条对应sql中的参数以及对应的值,没有参数时为null</param>
  156. /// <returns></returns>
  157. public bool ProcessTransaction(List<string> sqlCollection, List<Dictionary<string, object>> dictCollection)
  158. {
  159. bool processResult = false;
  160. if (sqlCollection == null || dictCollection == null || sqlCollection.Count != dictCollection.Count)
  161. {
  162. throw new Exception("没有sql指令 或者 参数个数不匹配");
  163. }
  164. DbConnection connection = providerFactory.CreateConnection();
  165. connection.ConnectionString = ConnectionString;
  166. DbTransaction transaction = null;
  167. try
  168. {
  169. if (connection.State != ConnectionState.Open)
  170. {
  171. connection.Open();
  172. }
  173. using (transaction = connection.BeginTransaction())
  174. {
  175. for (int i = 0; i < sqlCollection.Count; i++)
  176. {
  177. DbCommand command = CreateCommand(sqlCollection[i], dictCollection[i], CommandType.Text, connection);
  178. //增加事务与命令的绑定
  179. command.Transaction = transaction;
  180. command.ExecuteNonQuery();
  181. }
  182. //提交事务
  183. transaction.Commit();
  184. processResult = true;
  185. }
  186. }
  187. catch (Exception ex)
  188. {
  189. //回滚事务
  190. if (transaction != null)
  191. {
  192. transaction.Rollback();
  193. }
  194. Console.WriteLine(ex.Message, "事务处理时出现异常");
  195. processResult = false;
  196. }
  197. finally
  198. {
  199. connection.Close();
  200. }
  201. return processResult;
  202. }
  203. /// <summary>
  204. /// 执行查询,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略
  205. /// </summary>
  206. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  207. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  208. /// <param name="commandType">命令字符串类型:Text(默认)为 SQL文本,StoredProcedure为 存储过程名</param>
  209. /// <returns></returns>
  210. public object GetScalar(string sql, Dictionary<string, object> dict, CommandType commandType = CommandType.Text)
  211. {
  212. object result = null;
  213. using (DbCommand command = CreateCommand(sql, dict, commandType))
  214. {
  215. try
  216. {
  217. command.Connection.Open();
  218. result = command.ExecuteScalar();
  219. }
  220. catch (Exception ex)
  221. {
  222. Console.WriteLine(ex.Message, "获取第一行的第一列数据时出现异常");
  223. }
  224. finally
  225. {
  226. command.Connection.Close();
  227. }
  228. }
  229. return result;
  230. }
  231. /// <summary>
  232. /// 执行查询,并返回查询所返回的结果集中第一行的第一列。返回一个字符串
  233. /// </summary>
  234. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  235. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  236. /// <param name="commandType">命令字符串类型:Text(默认)为 SQL文本,StoredProcedure为 存储过程名</param>
  237. /// <returns></returns>
  238. public string GetScalarString(string sql, Dictionary<string, object> dict, CommandType commandType = CommandType.Text)
  239. {
  240. object result = GetScalar(sql, dict, commandType);
  241. if (result == null)
  242. {
  243. return string.Empty;
  244. }
  245. return result.ToString();
  246. }
  247. /// <summary>
  248. /// 执行查询,并返回查询所返回的结果集中第一行的第一列。返回一个整数
  249. /// </summary>
  250. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  251. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  252. /// <param name="commandType">命令字符串类型:Text(默认)为 SQL文本,StoredProcedure为 存储过程名</param>
  253. /// <returns></returns>
  254. public int GetScalarInt(string sql, Dictionary<string, object> dict, CommandType commandType = CommandType.Text)
  255. {
  256. object result = GetScalar(sql, dict, commandType);
  257. if (result == null)
  258. {
  259. return 0;
  260. }
  261. return Convert.ToInt32(result);
  262. }
  263. /// <summary>
  264. /// 读取数据,注意读取数据完成后,请调用dataReader.Close()进行手动关闭
  265. /// 代码示例:while (reader.Read()){string result=reader.GetString(0);} reader.Close();
  266. /// </summary>
  267. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  268. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  269. /// <param name="commandType">命令字符串类型:Text(默认)为 SQL文本,StoredProcedure为 存储过程名</param>
  270. /// <returns></returns>
  271. public DbDataReader GetDataReader(string sql, Dictionary<string, object> dict, CommandType commandType = CommandType.Text)
  272. {
  273. DbDataReader dataReader = null;
  274. DbCommand command = CreateCommand(sql, dict, commandType);
  275. try
  276. {
  277. command.Connection.Open();
  278. dataReader = command.ExecuteReader(CommandBehavior.CloseConnection);
  279. }
  280. catch (Exception ex)
  281. {
  282. if (dataReader != null)
  283. {
  284. dataReader.Close();
  285. }
  286. command.Connection.Close();
  287. Console.WriteLine(ex.Message, "获取只读数据流出现错误");
  288. }
  289. return dataReader;
  290. }
  291. /// <summary>
  292. /// 获取查询的结果,存入一个数据集中,该函数多用于返回多个数据表的查询
  293. /// </summary>
  294. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  295. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  296. /// <param name="commandType">命令字符串类型:Text(默认)为 SQL文本,StoredProcedure为 存储过程名</param>
  297. /// <returns></returns>
  298. public DataSet GetDataSet(string sql, Dictionary<string, object> dict, CommandType commandType = CommandType.Text)
  299. {
  300. DataSet ds = new DataSet("HansDataSet");
  301. using (DbCommand command = CreateCommand(sql, dict, commandType))
  302. {
  303. using (DbDataAdapter adapter = providerFactory.CreateDataAdapter())
  304. {
  305. adapter.SelectCommand = command;
  306. try
  307. {
  308. adapter.Fill(ds);
  309. }
  310. catch (Exception ex)
  311. {
  312. Console.WriteLine(ex.Message, "查询数据时出现异常");
  313. }
  314. }
  315. }
  316. return ds;
  317. }
  318. /// <summary>
  319. /// 获取查询的结果,存入一个数据表中
  320. /// </summary>
  321. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  322. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  323. /// <param name="commandType">命令字符串类型:Text(默认)为 SQL文本,StoredProcedure为 存储过程名</param>
  324. /// <returns></returns>
  325. public DataTable GetDataTable(string sql, Dictionary<string, object> dict, CommandType commandType = CommandType.Text)
  326. {
  327. DataTable dt = new DataTable("HansDataTable");
  328. using (DbCommand command = CreateCommand(sql, dict, commandType))
  329. {
  330. using (DbDataAdapter adapter = providerFactory.CreateDataAdapter())
  331. {
  332. adapter.SelectCommand = command;
  333. try
  334. {
  335. adapter.Fill(dt);
  336. }
  337. catch (Exception ex)
  338. {
  339. Console.WriteLine(ex.Message, "查询数据时出现异常");
  340. }
  341. }
  342. }
  343. return dt;
  344. }
  345. /// <summary>
  346. /// 获取数据表某一行数据,多用于获取数据库中某一个唯一的ID的数据行
  347. /// </summary>
  348. /// <param name="sql">要执行的sql语句 或者 存储过程名</param>
  349. /// <param name="dict">sql(或存储过程)中的参数以及具体的值</param>
  350. /// <param name="commandType">命令字符串类型:Text(默认)为 SQL文本,StoredProcedure为 存储过程名</param>
  351. /// <returns></returns>
  352. public DataRow GetDataRow(string sql, Dictionary<string, object> dict, CommandType commandType = CommandType.Text)
  353. {
  354. DataTable dt = GetDataTable(sql, dict, commandType);
  355. if (dt != null && dt.Rows.Count > 0)
  356. {
  357. return dt.Rows[0];
  358. }
  359. return null;
  360. }
  361. }
  362. }

四、默认的Program测试程序如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace MultiThreadMySqlDemo
  9. {
  10. class Program
  11. {
  12. //多线程并发mysql读写
  13. const string connectionString = "server=127.0.0.1;Database=testx;Uid=root;Pwd=root";
  14. static DbUtility dbUtility = DbUtility.GetInstance(connectionString, DatabaseType.MySql);
  15. static void Main(string[] args)
  16. {
  17. try
  18. {
  19. InitCreateTable();
  20. }
  21. catch (Exception ex)
  22. {
  23. Console.WriteLine(ex.Message);
  24. }
  25. Task.Factory.StartNew(() =>
  26. {
  27. for (int i = 0; i < 10; i++)
  28. {
  29. PrintCurrentData(GetCurrentDataWithLock);
  30. PrintCurrentData(GetCurrentData);
  31. Thread.Sleep(500);
  32. }
  33. });
  34. Task.Run(() =>
  35. {
  36. for (int i = 0; i < 10; i++)
  37. {
  38. ModifyData();
  39. Thread.Sleep(500);
  40. }
  41. });
  42. Console.ReadLine();
  43. }
  44. /// <summary>
  45. /// 初始化创建数据库
  46. /// </summary>
  47. private static void InitCreateTable()
  48. {
  49. string sqlCreateTable = @"CREATE TABLE IF NOT EXISTS `busbar_measure_fai` (
  50. `CoreId` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增编号',
  51. `ModuleBarcode` varchar(100) NOT NULL DEFAULT '' COMMENT '模组条码',
  52. `EquipmentNo` varchar(50) NOT NULL DEFAULT '' COMMENT '设备编号',
  53. `ProcessEndTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '处理结束时间',
  54. `ProcessResult` varchar(10) NOT NULL DEFAULT '' COMMENT '处理结果',
  55. `MeasureDistance1` float NOT NULL DEFAULT '0' COMMENT '首件测距1',
  56. `MeasureDistance2` float NOT NULL DEFAULT '0' COMMENT '首件测距2',
  57. `MeasureDistance3` float NOT NULL DEFAULT '0' COMMENT '首件测距3',
  58. PRIMARY KEY (`CoreId`),
  59. KEY `IDX_BSB_WELD_FAI_TIME` (`ProcessEndTime`) USING BTREE
  60. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='首件测距表';";
  61. dbUtility.UpdateData(sqlCreateTable, null);
  62. }
  63. /// <summary>
  64. /// 获得当前表的全部数据
  65. /// </summary>
  66. /// <returns></returns>
  67. private static DataTable GetCurrentData()
  68. {
  69. return dbUtility.GetDataTable("select CoreId,ModuleBarcode,ProcessEndTime from busbar_measure_fai", null);
  70. }
  71. /// <summary>
  72. /// 获得当前表的全部数据【增加锁】
  73. /// from tb lock in share mode
  74. /// </summary>
  75. /// <returns></returns>
  76. private static DataTable GetCurrentDataWithLock()
  77. {
  78. return dbUtility.GetDataTable("select CoreId,ModuleBarcode,ProcessEndTime from busbar_measure_fai lock in share mode", null);
  79. }
  80. /// <summary>
  81. /// 打印当前数据
  82. /// </summary>
  83. /// <param name="funcGetData">一个返回当前数据表的方法</param>
  84. private static void PrintCurrentData(Func<DataTable> funcGetData)
  85. {
  86. DataTable dataTable = funcGetData();
  87. Console.WriteLine($"读取当前数据行数:【{dataTable.Rows.Count}】");
  88. for (int i = 0; i < dataTable.Rows.Count; i++)
  89. {
  90. Console.WriteLine($"----行【{i + 1}】:【{dataTable.Rows[i]["CoreId"]},{dataTable.Rows[i]["ModuleBarcode"]},{dataTable.Rows[i]["ProcessEndTime"]}】");
  91. }
  92. }
  93. /// <summary>
  94. /// 删除指定的数据后再添加
  95. /// </summary>
  96. /// <param name="moduleBarcode"></param>
  97. /// <returns></returns>
  98. private static int DeleteAndAddData(string moduleBarcode)
  99. {
  100. string sqlUpdate = @"delete from busbar_measure_fai where ModuleBarcode=?ModuleBarcode;
  101. insert into busbar_measure_fai (ModuleBarcode,EquipmentNo,ProcessEndTime,ProcessResult,MeasureDistance1,MeasureDistance2,MeasureDistance3)
  102. values (?ModuleBarcode,?EquipmentNo,?ProcessEndTime,?ProcessResult,?MeasureDistance1,?MeasureDistance2,?MeasureDistance3)";
  103. Dictionary<string, object> dict = new Dictionary<string, object>();
  104. dict.Add("ModuleBarcode", moduleBarcode);
  105. dict.Add("EquipmentNo", "XX焊接");
  106. dict.Add("ProcessEndTime", DateTime.Now);
  107. dict.Add("ProcessResult", "OK");
  108. dict.Add("MeasureDistance1", 1.1F);
  109. dict.Add("MeasureDistance2", 2.2F);
  110. dict.Add("MeasureDistance3", 3.3F);
  111. return dbUtility.UpdateData(sqlUpdate, dict);
  112. }
  113. /// <summary>
  114. /// 更新数据
  115. /// </summary>
  116. public static void ModifyData()
  117. {
  118. Random random = new Random(Guid.NewGuid().GetHashCode());
  119. int affectRow = DeleteAndAddData($"M{random.Next(1, 100).ToString("D2")}");
  120. Console.WriteLine($"更新当前数据,受影响的行数:【{affectRow}】");
  121. }
  122. }
  123. }

五、程序运行如图:

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/750539
推荐阅读
相关标签
  

闽ICP备14008679号