You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

950 lines
39 KiB

4 years ago
  1. #if MYSQL_6_9
  2. // Copyright ?2004, 2014, Oracle and/or its affiliates. All rights reserved.
  3. //
  4. // MySQL Connector/NET is licensed under the terms of the GPLv2
  5. // <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
  6. // MySQL Connectors. There are special exceptions to the terms and
  7. // conditions of the GPLv2 as it is applied to this software, see the
  8. // FLOSS License Exception
  9. // <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
  10. //
  11. // This program is free software; you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published
  13. // by the Free Software Foundation; version 2 of the License.
  14. //
  15. // This program is distributed in the hope that it will be useful, but
  16. // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  18. // for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License along
  21. // with this program; if not, write to the Free Software Foundation, Inc.,
  22. // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. using System.Data;
  24. using Externals.MySql.Data.MySqlClient;
  25. using System.Text;
  26. using System.Threading.Tasks;
  27. using System.Threading;
  28. using System;
  29. namespace Externals.MySql.Data.MySqlClient
  30. {
  31. /// <summary>
  32. /// Helper class that makes it easier to work with the provider.
  33. /// </summary>
  34. internal sealed class MySqlHelper
  35. {
  36. enum CharClass : byte
  37. {
  38. None,
  39. Quote,
  40. Backslash
  41. }
  42. private static string stringOfBackslashChars = "\u005c\u00a5\u0160\u20a9\u2216\ufe68\uff3c";
  43. private static string stringOfQuoteChars =
  44. "\u0022\u0027\u0060\u00b4\u02b9\u02ba\u02bb\u02bc\u02c8\u02ca\u02cb\u02d9\u0300\u0301\u2018\u2019\u201a\u2032\u2035\u275b\u275c\uff07";
  45. private static CharClass[] charClassArray = makeCharClassArray();
  46. // this class provides only static methods
  47. private MySqlHelper()
  48. {
  49. }
  50. #region ExecuteNonQuery
  51. /// <summary>
  52. /// Executes a single command against a MySQL database. The <see cref="MySqlConnection"/> is assumed to be
  53. /// open when the method is called and remains open after the method completes.
  54. /// </summary>
  55. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  56. /// <param name="commandText">SQL command to be executed</param>
  57. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command.</param>
  58. /// <returns></returns>
  59. public static int ExecuteNonQuery(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  60. {
  61. //create a command and prepare it for execution
  62. MySqlCommand cmd = new MySqlCommand();
  63. cmd.Connection = connection;
  64. cmd.CommandText = commandText;
  65. cmd.CommandType = CommandType.Text;
  66. if (commandParameters != null)
  67. foreach (MySqlParameter p in commandParameters)
  68. cmd.Parameters.Add(p);
  69. int result = cmd.ExecuteNonQuery();
  70. cmd.Parameters.Clear();
  71. return result;
  72. }
  73. /// <summary>
  74. /// Executes a single command against a MySQL database. A new <see cref="MySqlConnection"/> is created
  75. /// using the <see cref="MySqlConnection.ConnectionString"/> given.
  76. /// </summary>
  77. /// <param name="connectionString"><see cref="MySqlConnection.ConnectionString"/> to use</param>
  78. /// <param name="commandText">SQL command to be executed</param>
  79. /// <param name="parms">Array of <see cref="MySqlParameter"/> objects to use with the command.</param>
  80. /// <returns></returns>
  81. public static int ExecuteNonQuery(string connectionString, string commandText, params MySqlParameter[] parms)
  82. {
  83. //create & open a SqlConnection, and dispose of it after we are done.
  84. using (MySqlConnection cn = new MySqlConnection(connectionString))
  85. {
  86. cn.Open();
  87. //call the overload that takes a connection in place of the connection string
  88. return ExecuteNonQuery(cn, commandText, parms);
  89. }
  90. }
  91. #endregion
  92. #region ExecuteDataSet
  93. /// <summary>
  94. /// Executes a single SQL command and returns the first row of the resultset. A new MySqlConnection object
  95. /// is created, opened, and closed during this method.
  96. /// </summary>
  97. /// <param name="connectionString">Settings to be used for the connection</param>
  98. /// <param name="commandText">Command to execute</param>
  99. /// <param name="parms">Parameters to use for the command</param>
  100. /// <returns>DataRow containing the first row of the resultset</returns>
  101. public static DataRow ExecuteDataRow(string connectionString, string commandText, params MySqlParameter[] parms)
  102. {
  103. DataSet ds = ExecuteDataset(connectionString, commandText, parms);
  104. if (ds == null) return null;
  105. if (ds.Tables.Count == 0) return null;
  106. if (ds.Tables[0].Rows.Count == 0) return null;
  107. return ds.Tables[0].Rows[0];
  108. }
  109. /// <summary>
  110. /// Executes a single SQL command and returns the resultset in a <see cref="DataSet"/>.
  111. /// A new MySqlConnection object is created, opened, and closed during this method.
  112. /// </summary>
  113. /// <param name="connectionString">Settings to be used for the connection</param>
  114. /// <param name="commandText">Command to execute</param>
  115. /// <returns><see cref="DataSet"/> containing the resultset</returns>
  116. public static DataSet ExecuteDataset(string connectionString, string commandText)
  117. {
  118. //pass through the call providing null for the set of SqlParameters
  119. return ExecuteDataset(connectionString, commandText, (MySqlParameter[])null);
  120. }
  121. /// <summary>
  122. /// Executes a single SQL command and returns the resultset in a <see cref="DataSet"/>.
  123. /// A new MySqlConnection object is created, opened, and closed during this method.
  124. /// </summary>
  125. /// <param name="connectionString">Settings to be used for the connection</param>
  126. /// <param name="commandText">Command to execute</param>
  127. /// <param name="commandParameters">Parameters to use for the command</param>
  128. /// <returns><see cref="DataSet"/> containing the resultset</returns>
  129. public static DataSet ExecuteDataset(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  130. {
  131. //create & open a SqlConnection, and dispose of it after we are done.
  132. using (MySqlConnection cn = new MySqlConnection(connectionString))
  133. {
  134. cn.Open();
  135. //call the overload that takes a connection in place of the connection string
  136. return ExecuteDataset(cn, commandText, commandParameters);
  137. }
  138. }
  139. /// <summary>
  140. /// Executes a single SQL command and returns the resultset in a <see cref="DataSet"/>.
  141. /// The state of the <see cref="MySqlConnection"/> object remains unchanged after execution
  142. /// of this method.
  143. /// </summary>
  144. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  145. /// <param name="commandText">Command to execute</param>
  146. /// <returns><see cref="DataSet"/> containing the resultset</returns>
  147. public static DataSet ExecuteDataset(MySqlConnection connection, string commandText)
  148. {
  149. //pass through the call providing null for the set of SqlParameters
  150. return ExecuteDataset(connection, commandText, (MySqlParameter[])null);
  151. }
  152. /// <summary>
  153. /// Executes a single SQL command and returns the resultset in a <see cref="DataSet"/>.
  154. /// The state of the <see cref="MySqlConnection"/> object remains unchanged after execution
  155. /// of this method.
  156. /// </summary>
  157. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  158. /// <param name="commandText">Command to execute</param>
  159. /// <param name="commandParameters">Parameters to use for the command</param>
  160. /// <returns><see cref="DataSet"/> containing the resultset</returns>
  161. public static DataSet ExecuteDataset(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  162. {
  163. //create a command and prepare it for execution
  164. MySqlCommand cmd = new MySqlCommand();
  165. cmd.Connection = connection;
  166. cmd.CommandText = commandText;
  167. cmd.CommandType = CommandType.Text;
  168. if (commandParameters != null)
  169. foreach (MySqlParameter p in commandParameters)
  170. cmd.Parameters.Add(p);
  171. //create the DataAdapter & DataSet
  172. MySqlDataAdapter da = new MySqlDataAdapter(cmd);
  173. DataSet ds = new DataSet();
  174. //fill the DataSet using default values for DataTable names, etc.
  175. da.Fill(ds);
  176. // detach the MySqlParameters from the command object, so they can be used again.
  177. cmd.Parameters.Clear();
  178. //return the dataset
  179. return ds;
  180. }
  181. /// <summary>
  182. /// Updates the given table with data from the given <see cref="DataSet"/>
  183. /// </summary>
  184. /// <param name="connectionString">Settings to use for the update</param>
  185. /// <param name="commandText">Command text to use for the update</param>
  186. /// <param name="ds"><see cref="DataSet"/> containing the new data to use in the update</param>
  187. /// <param name="tablename">Tablename in the dataset to update</param>
  188. public static void UpdateDataSet(string connectionString, string commandText, DataSet ds, string tablename)
  189. {
  190. MySqlConnection cn = new MySqlConnection(connectionString);
  191. cn.Open();
  192. MySqlDataAdapter da = new MySqlDataAdapter(commandText, cn);
  193. MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
  194. cb.ToString();
  195. da.Update(ds, tablename);
  196. cn.Close();
  197. }
  198. #endregion
  199. #region ExecuteDataReader
  200. /// <summary>
  201. /// Executes a single command against a MySQL database, possibly inside an existing transaction.
  202. /// </summary>
  203. /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
  204. /// <param name="transaction"><see cref="MySqlTransaction"/> object to use for the command</param>
  205. /// <param name="commandText">Command text to use</param>
  206. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  207. /// <param name="ExternalConn">True if the connection should be preserved, false if not</param>
  208. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  209. private static MySqlDataReader ExecuteReader(MySqlConnection connection, MySqlTransaction transaction, string commandText, MySqlParameter[] commandParameters, bool ExternalConn)
  210. {
  211. //create a command and prepare it for execution
  212. MySqlCommand cmd = new MySqlCommand();
  213. cmd.Connection = connection;
  214. cmd.Transaction = transaction;
  215. cmd.CommandText = commandText;
  216. cmd.CommandType = CommandType.Text;
  217. if (commandParameters != null)
  218. foreach (MySqlParameter p in commandParameters)
  219. cmd.Parameters.Add(p);
  220. //create a reader
  221. MySqlDataReader dr;
  222. // call ExecuteReader with the appropriate CommandBehavior
  223. if (ExternalConn)
  224. {
  225. dr = cmd.ExecuteReader();
  226. }
  227. else
  228. {
  229. dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
  230. }
  231. // detach the SqlParameters from the command object, so they can be used again.
  232. cmd.Parameters.Clear();
  233. return dr;
  234. }
  235. /// <summary>
  236. /// Executes a single command against a MySQL database.
  237. /// </summary>
  238. /// <param name="connectionString">Settings to use for this command</param>
  239. /// <param name="commandText">Command text to use</param>
  240. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  241. public static MySqlDataReader ExecuteReader(string connectionString, string commandText)
  242. {
  243. //pass through the call providing null for the set of SqlParameters
  244. return ExecuteReader(connectionString, commandText, (MySqlParameter[])null);
  245. }
  246. /// <summary>
  247. /// Executes a single command against a MySQL database.
  248. /// </summary>
  249. /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
  250. /// <param name="commandText">Command text to use</param>
  251. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  252. public static MySqlDataReader ExecuteReader(MySqlConnection connection, string commandText)
  253. {
  254. //pass through the call providing null for the set of SqlParameters
  255. return ExecuteReader(connection, null, commandText, (MySqlParameter[])null, true);
  256. }
  257. /// <summary>
  258. /// Executes a single command against a MySQL database.
  259. /// </summary>
  260. /// <param name="connectionString">Settings to use for this command</param>
  261. /// <param name="commandText">Command text to use</param>
  262. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  263. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  264. public static MySqlDataReader ExecuteReader(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  265. {
  266. //create & open a SqlConnection
  267. MySqlConnection cn = new MySqlConnection(connectionString);
  268. cn.Open();
  269. //call the private overload that takes an internally owned connection in place of the connection string
  270. return ExecuteReader(cn, null, commandText, commandParameters, false);
  271. }
  272. /// <summary>
  273. /// Executes a single command against a MySQL database.
  274. /// </summary>
  275. /// <param name="connection">Connection to use for the command</param>
  276. /// <param name="commandText">Command text to use</param>
  277. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  278. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  279. public static MySqlDataReader ExecuteReader(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  280. {
  281. //call the private overload that takes an internally owned connection in place of the connection string
  282. return ExecuteReader(connection, null, commandText, commandParameters, true);
  283. }
  284. #endregion
  285. #region ExecuteScalar
  286. /// <summary>
  287. /// Execute a single command against a MySQL database.
  288. /// </summary>
  289. /// <param name="connectionString">Settings to use for the update</param>
  290. /// <param name="commandText">Command text to use for the update</param>
  291. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  292. public static object ExecuteScalar(string connectionString, string commandText)
  293. {
  294. //pass through the call providing null for the set of MySqlParameters
  295. return ExecuteScalar(connectionString, commandText, (MySqlParameter[])null);
  296. }
  297. /// <summary>
  298. /// Execute a single command against a MySQL database.
  299. /// </summary>
  300. /// <param name="connectionString">Settings to use for the command</param>
  301. /// <param name="commandText">Command text to use for the command</param>
  302. /// <param name="commandParameters">Parameters to use for the command</param>
  303. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  304. public static object ExecuteScalar(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  305. {
  306. //create & open a SqlConnection, and dispose of it after we are done.
  307. using (MySqlConnection cn = new MySqlConnection(connectionString))
  308. {
  309. cn.Open();
  310. //call the overload that takes a connection in place of the connection string
  311. return ExecuteScalar(cn, commandText, commandParameters);
  312. }
  313. }
  314. /// <summary>
  315. /// Execute a single command against a MySQL database.
  316. /// </summary>
  317. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  318. /// <param name="commandText">Command text to use for the command</param>
  319. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  320. public static object ExecuteScalar(MySqlConnection connection, string commandText)
  321. {
  322. //pass through the call providing null for the set of MySqlParameters
  323. return ExecuteScalar(connection, commandText, (MySqlParameter[])null);
  324. }
  325. /// <summary>
  326. /// Execute a single command against a MySQL database.
  327. /// </summary>
  328. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  329. /// <param name="commandText">Command text to use for the command</param>
  330. /// <param name="commandParameters">Parameters to use for the command</param>
  331. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  332. public static object ExecuteScalar(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  333. {
  334. //create a command and prepare it for execution
  335. MySqlCommand cmd = new MySqlCommand();
  336. cmd.Connection = connection;
  337. cmd.CommandText = commandText;
  338. cmd.CommandType = CommandType.Text;
  339. if (commandParameters != null)
  340. foreach (MySqlParameter p in commandParameters)
  341. cmd.Parameters.Add(p);
  342. //execute the command & return the results
  343. object retval = cmd.ExecuteScalar();
  344. // detach the SqlParameters from the command object, so they can be used again.
  345. cmd.Parameters.Clear();
  346. return retval;
  347. }
  348. #endregion
  349. #region Utility methods
  350. private static CharClass[] makeCharClassArray()
  351. {
  352. CharClass[] a = new CharClass[65536];
  353. foreach (char c in stringOfBackslashChars)
  354. {
  355. a[c] = CharClass.Backslash;
  356. }
  357. foreach (char c in stringOfQuoteChars)
  358. {
  359. a[c] = CharClass.Quote;
  360. }
  361. return a;
  362. }
  363. private static bool needsQuoting(string s)
  364. {
  365. foreach (char c in s)
  366. {
  367. if (charClassArray[c] != CharClass.None)
  368. {
  369. return true;
  370. }
  371. }
  372. return false;
  373. }
  374. /// <summary>
  375. /// Escapes the string.
  376. /// </summary>
  377. /// <param name="value">The string to escape</param>
  378. /// <returns>The string with all quotes escaped.</returns>
  379. public static string EscapeString(string value)
  380. {
  381. if (!needsQuoting(value))
  382. return value;
  383. StringBuilder sb = new StringBuilder();
  384. foreach (char c in value)
  385. {
  386. CharClass charClass = charClassArray[c];
  387. if (charClass != CharClass.None)
  388. {
  389. sb.Append("\\");
  390. }
  391. sb.Append(c);
  392. }
  393. return sb.ToString();
  394. }
  395. public static string DoubleQuoteString(string value)
  396. {
  397. if (!needsQuoting(value))
  398. return value;
  399. StringBuilder sb = new StringBuilder();
  400. foreach (char c in value)
  401. {
  402. CharClass charClass = charClassArray[c];
  403. if (charClass == CharClass.Quote)
  404. sb.Append(c);
  405. else if (charClass == CharClass.Backslash)
  406. sb.Append("\\");
  407. sb.Append(c);
  408. }
  409. return sb.ToString();
  410. }
  411. #endregion
  412. #region Async
  413. #region DataRow
  414. /// <summary>
  415. /// Async version of ExecuteDataRow
  416. /// </summary>
  417. /// <param name="connectionString">Settings to be used for the connection</param>
  418. /// <param name="commandText">Command to execute</param>
  419. /// <param name="parms">Parameters to use for the command</param>
  420. /// <returns>DataRow containing the first row of the resultset</returns>
  421. public static Task<DataRow> ExecuteDataRowAsync(string connectionString, string commandText, params MySqlParameter[] parms)
  422. {
  423. return ExecuteDataRowAsync(connectionString, commandText, CancellationToken.None, parms);
  424. }
  425. public static Task<DataRow> ExecuteDataRowAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] parms)
  426. {
  427. var result = new TaskCompletionSource<DataRow>();
  428. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  429. {
  430. try
  431. {
  432. var row = ExecuteDataRow(connectionString, commandText, parms);
  433. result.SetResult(row);
  434. }
  435. catch (Exception ex)
  436. {
  437. result.SetException(ex);
  438. }
  439. }
  440. else
  441. {
  442. result.SetCanceled();
  443. }
  444. return result.Task;
  445. }
  446. #endregion
  447. #region NonQuery
  448. /// <summary>
  449. /// Async version of ExecuteNonQuery
  450. /// </summary>
  451. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  452. /// <param name="commandText">SQL command to be executed</param>
  453. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command.</param>
  454. /// <returns>Rows affected</returns>
  455. public static Task<int> ExecuteNonQueryAsync(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  456. {
  457. return ExecuteNonQueryAsync(connection, commandText, CancellationToken.None, commandParameters);
  458. }
  459. public static Task<int> ExecuteNonQueryAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  460. {
  461. var result = new TaskCompletionSource<int>();
  462. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  463. {
  464. try
  465. {
  466. var queryResult = ExecuteNonQuery(connection, commandText, commandParameters);
  467. result.SetResult(queryResult);
  468. }
  469. catch (Exception ex)
  470. {
  471. result.SetException(ex);
  472. }
  473. }
  474. else
  475. {
  476. result.SetCanceled();
  477. }
  478. return result.Task;
  479. }
  480. /// <summary>
  481. /// Async version of ExecuteNonQuery
  482. /// </summary>
  483. /// <param name="connectionString"><see cref="MySqlConnection.ConnectionString"/> to use</param>
  484. /// <param name="commandText">SQL command to be executed</param>
  485. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command.</param>
  486. /// <returns>Rows affected</returns>
  487. public static Task<int> ExecuteNonQueryAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  488. {
  489. return ExecuteNonQueryAsync(connectionString, commandText, CancellationToken.None, commandParameters);
  490. }
  491. public static Task<int> ExecuteNonQueryAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  492. {
  493. var result = new TaskCompletionSource<int>();
  494. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  495. {
  496. try
  497. {
  498. var queryResult = ExecuteNonQuery(connectionString, commandText, commandParameters);
  499. result.SetResult(queryResult);
  500. }
  501. catch (Exception ex)
  502. {
  503. result.SetException(ex);
  504. }
  505. }
  506. else
  507. {
  508. result.SetCanceled();
  509. }
  510. return result.Task;
  511. }
  512. #endregion
  513. #region DataSet
  514. /// <summary>
  515. /// Async version of ExecuteDataset
  516. /// </summary>
  517. /// <param name="connectionString">Settings to be used for the connection</param>
  518. /// <param name="commandText">Command to execute</param>
  519. /// <returns><see cref="DataSet"/> containing the resultset</returns>
  520. public static Task<DataSet> ExecuteDatasetAsync(string connectionString, string commandText)
  521. {
  522. return ExecuteDatasetAsync(connectionString, commandText, CancellationToken.None, (MySqlParameter[])null);
  523. }
  524. public static Task<DataSet> ExecuteDatasetAsync(string connectionString, string commandText, CancellationToken cancellationToken)
  525. {
  526. return ExecuteDatasetAsync(connectionString, commandText, cancellationToken, (MySqlParameter[])null);
  527. }
  528. /// <summary>
  529. /// Async version of ExecuteDataset
  530. /// </summary>
  531. /// <param name="connectionString">Settings to be used for the connection</param>
  532. /// <param name="commandText">Command to execute</param>
  533. /// <param name="commandParameters">Parameters to use for the command</param>
  534. /// <returns><see cref="DataSet"/> containing the resultset</returns>
  535. public static Task<DataSet> ExecuteDatasetAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  536. {
  537. return ExecuteDatasetAsync(connectionString, commandText, CancellationToken.None, commandParameters);
  538. }
  539. public static Task<DataSet> ExecuteDatasetAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  540. {
  541. var result = new TaskCompletionSource<DataSet>();
  542. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  543. {
  544. try
  545. {
  546. var dataset = ExecuteDataset(connectionString, commandText, commandParameters);
  547. result.SetResult(dataset);
  548. }
  549. catch (Exception ex)
  550. {
  551. result.SetException(ex);
  552. }
  553. }
  554. else
  555. {
  556. result.SetCanceled();
  557. }
  558. return result.Task;
  559. }
  560. /// <summary>
  561. /// Async version of ExecuteDataset
  562. /// </summary>
  563. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  564. /// <param name="commandText">Command to execute</param>
  565. /// <returns><see cref="DataSet"/> containing the resultset</returns>
  566. public static Task<DataSet> ExecuteDatasetAsync(MySqlConnection connection, string commandText)
  567. {
  568. return ExecuteDatasetAsync(connection, commandText, CancellationToken.None, (MySqlParameter[])null);
  569. }
  570. public static Task<DataSet> ExecuteDatasetAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken)
  571. {
  572. return ExecuteDatasetAsync(connection, commandText, cancellationToken, (MySqlParameter[])null);
  573. }
  574. /// <summary>
  575. /// Async version of ExecuteDataset
  576. /// </summary>
  577. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  578. /// <param name="commandText">Command to execute</param>
  579. /// <param name="commandParameters">Parameters to use for the command</param>
  580. /// <returns><see cref="DataSet"/> containing the resultset</returns>
  581. public static Task<DataSet> ExecuteDatasetAsync(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  582. {
  583. return ExecuteDatasetAsync(connection, commandText, CancellationToken.None, commandParameters);
  584. }
  585. public static Task<DataSet> ExecuteDatasetAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  586. {
  587. var result = new TaskCompletionSource<DataSet>();
  588. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  589. {
  590. try
  591. {
  592. var dataset = ExecuteDataset(connection, commandText, commandParameters);
  593. result.SetResult(dataset);
  594. }
  595. catch (Exception ex)
  596. {
  597. result.SetException(ex);
  598. }
  599. }
  600. else
  601. {
  602. result.SetCanceled();
  603. }
  604. return result.Task;
  605. }
  606. /// <summary>
  607. /// Async version of UpdateDataset
  608. /// </summary>
  609. /// <param name="connectionString">Settings to use for the update</param>
  610. /// <param name="commandText">Command text to use for the update</param>
  611. /// <param name="ds"><see cref="DataSet"/> containing the new data to use in the update</param>
  612. /// <param name="tablename">Tablename in the dataset to update</param>
  613. public static Task UpdateDataSetAsync(string connectionString, string commandText, DataSet ds, string tablename)
  614. {
  615. return UpdateDataSetAsync(connectionString, commandText, ds, tablename, CancellationToken.None);
  616. }
  617. public static Task UpdateDataSetAsync(string connectionString, string commandText, DataSet ds, string tablename, CancellationToken cancellationToken)
  618. {
  619. var result = new TaskCompletionSource<bool>();
  620. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  621. {
  622. try
  623. {
  624. UpdateDataSet(connectionString, commandText, ds, tablename);
  625. result.SetResult(true);
  626. }
  627. catch (Exception ex)
  628. {
  629. result.SetException(ex);
  630. }
  631. }
  632. else
  633. {
  634. result.SetCanceled();
  635. }
  636. return result.Task;
  637. }
  638. #endregion
  639. #region DataReader
  640. /// <summary>
  641. /// Async version of ExecuteReader
  642. /// </summary>
  643. /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
  644. /// <param name="transaction"><see cref="MySqlTransaction"/> object to use for the command</param>
  645. /// <param name="commandText">Command text to use</param>
  646. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  647. /// <param name="ExternalConn">True if the connection should be preserved, false if not</param>
  648. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  649. private static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, MySqlTransaction transaction, string commandText, MySqlParameter[] commandParameters, bool ExternalConn)
  650. {
  651. return ExecuteReaderAsync(connection, transaction, commandText, commandParameters, ExternalConn, CancellationToken.None);
  652. }
  653. private static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, MySqlTransaction transaction, string commandText, MySqlParameter[] commandParameters, bool ExternalConn, CancellationToken cancellationToken)
  654. {
  655. var result = new TaskCompletionSource<MySqlDataReader>();
  656. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  657. {
  658. try
  659. {
  660. var reader = ExecuteReader(connection, transaction, commandText, commandParameters, ExternalConn);
  661. result.SetResult(reader);
  662. }
  663. catch (Exception ex)
  664. {
  665. result.SetException(ex);
  666. }
  667. }
  668. else
  669. {
  670. result.SetCanceled();
  671. }
  672. return result.Task;
  673. }
  674. /// <summary>
  675. /// Async version of ExecuteReader
  676. /// </summary>
  677. /// <param name="connectionString">Settings to use for this command</param>
  678. /// <param name="commandText">Command text to use</param>
  679. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  680. public static Task<MySqlDataReader> ExecuteReaderAsync(string connectionString, string commandText)
  681. {
  682. return ExecuteReaderAsync(connectionString, commandText, CancellationToken.None, (MySqlParameter[])null);
  683. }
  684. public static Task<MySqlDataReader> ExecuteReaderAsync(string connectionString, string commandText, CancellationToken cancellationToken)
  685. {
  686. return ExecuteReaderAsync(connectionString, commandText, cancellationToken, (MySqlParameter[])null);
  687. }
  688. /// <summary>
  689. /// Async version of ExecuteReader
  690. /// </summary>
  691. /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
  692. /// <param name="commandText">Command text to use</param>
  693. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  694. public static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, string commandText)
  695. {
  696. return ExecuteReaderAsync(connection, null, commandText, (MySqlParameter[])null, true, CancellationToken.None);
  697. }
  698. public static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken)
  699. {
  700. return ExecuteReaderAsync(connection, null, commandText, (MySqlParameter[])null, true, cancellationToken);
  701. }
  702. /// <summary>
  703. /// Async version of ExecuteReader
  704. /// </summary>
  705. /// <param name="connectionString">Settings to use for this command</param>
  706. /// <param name="commandText">Command text to use</param>
  707. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  708. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  709. public static Task<MySqlDataReader> ExecuteReaderAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  710. {
  711. return ExecuteReaderAsync(connectionString, commandText, CancellationToken.None, commandParameters);
  712. }
  713. public static Task<MySqlDataReader> ExecuteReaderAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  714. {
  715. var result = new TaskCompletionSource<MySqlDataReader>();
  716. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  717. {
  718. try
  719. {
  720. var reader = ExecuteReader(connectionString, commandText, commandParameters);
  721. result.SetResult(reader);
  722. }
  723. catch (Exception ex)
  724. {
  725. result.SetException(ex);
  726. }
  727. }
  728. else
  729. {
  730. result.SetCanceled();
  731. }
  732. return result.Task;
  733. }
  734. /// <summary>
  735. /// Async version of ExecuteReader
  736. /// </summary>
  737. /// <param name="connection">Connection to use for the command</param>
  738. /// <param name="commandText">Command text to use</param>
  739. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  740. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  741. public static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  742. {
  743. return ExecuteReaderAsync(connection, null, commandText, commandParameters, true, CancellationToken.None);
  744. }
  745. public static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  746. {
  747. return ExecuteReaderAsync(connection, null, commandText, commandParameters, true, cancellationToken);
  748. }
  749. #endregion
  750. #region Scalar
  751. /// <summary>
  752. /// Async version of ExecuteScalar
  753. /// </summary>
  754. /// <param name="connectionString">Settings to use for the update</param>
  755. /// <param name="commandText">Command text to use for the update</param>
  756. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  757. public static Task<object> ExecuteScalarAsync(string connectionString, string commandText)
  758. {
  759. return ExecuteScalarAsync(connectionString, commandText, CancellationToken.None, (MySqlParameter[])null);
  760. }
  761. public static Task<object> ExecuteScalarAsync(string connectionString, string commandText, CancellationToken cancellationToken)
  762. {
  763. return ExecuteScalarAsync(connectionString, commandText, cancellationToken, (MySqlParameter[])null);
  764. }
  765. /// <summary>
  766. /// Async version of ExecuteScalar
  767. /// </summary>
  768. /// <param name="connectionString">Settings to use for the command</param>
  769. /// <param name="commandText">Command text to use for the command</param>
  770. /// <param name="commandParameters">Parameters to use for the command</param>
  771. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  772. public static Task<object> ExecuteScalarAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  773. {
  774. return ExecuteScalarAsync(connectionString, commandText, CancellationToken.None, commandParameters);
  775. }
  776. public static Task<object> ExecuteScalarAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  777. {
  778. var result = new TaskCompletionSource<object>();
  779. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  780. {
  781. try
  782. {
  783. var scalarResult = ExecuteScalar(connectionString, commandText, commandParameters);
  784. result.SetResult(scalarResult);
  785. }
  786. catch (Exception ex)
  787. {
  788. result.SetException(ex);
  789. }
  790. }
  791. else
  792. {
  793. result.SetCanceled();
  794. }
  795. return result.Task;
  796. }
  797. /// <summary>
  798. /// Async version of ExecuteScalar
  799. /// </summary>
  800. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  801. /// <param name="commandText">Command text to use for the command</param>
  802. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  803. public static Task<object> ExecuteScalarAsync(MySqlConnection connection, string commandText)
  804. {
  805. return ExecuteScalarAsync(connection, commandText, CancellationToken.None, (MySqlParameter[])null);
  806. }
  807. public static Task<object> ExecuteScalarAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken)
  808. {
  809. return ExecuteScalarAsync(connection, commandText, cancellationToken, (MySqlParameter[])null);
  810. }
  811. /// <summary>
  812. /// Async version of ExecuteScalar
  813. /// </summary>
  814. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  815. /// <param name="commandText">Command text to use for the command</param>
  816. /// <param name="commandParameters">Parameters to use for the command</param>
  817. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  818. public static Task<object> ExecuteScalarAsync(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  819. {
  820. return ExecuteScalarAsync(connection, commandText, CancellationToken.None, commandParameters);
  821. }
  822. public static Task<object> ExecuteScalarAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  823. {
  824. var result = new TaskCompletionSource<object>();
  825. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  826. {
  827. try
  828. {
  829. var scalarResult = ExecuteScalar(connection, commandText, commandParameters);
  830. result.SetResult(scalarResult);
  831. }
  832. catch (Exception ex)
  833. {
  834. result.SetException(ex);
  835. }
  836. }
  837. else
  838. {
  839. result.SetCanceled();
  840. }
  841. return result.Task;
  842. }
  843. #endregion
  844. #endregion
  845. }
  846. }
  847. #endif