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.

660 lines
30 KiB

4 years ago
  1. #if MYSQL_6_10
  2. // Copyright ?2004, 2018, 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;
  24. using System.Data;
  25. using System.Linq;
  26. using System.Text;
  27. using System.Threading;
  28. using System.Threading.Tasks;
  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 partial 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">The <see cref="MySqlConnection"/> object to use</param>
  56. /// <param name="commandText">The SQL command to be executed.</param>
  57. /// <param name="commandParameters">An array of <see cref="MySqlParameter"/> objects to use with the command.</param>
  58. /// <returns>The number of affected records.</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.
  75. /// </summary>
  76. /// <param name="connectionString"><see cref="MySqlConnection.ConnectionString"/> to use.</param>
  77. /// <param name="commandText">The SQL command to be executed.</param>
  78. /// <param name="parms">An rray of <see cref="MySqlParameter"/> objects to use with the command.</param>
  79. /// <returns>The number of affected records.</returns>
  80. /// <remarks>A new <see cref="MySqlConnection"/> is created using the <see cref="MySqlConnection.ConnectionString"/> given.</remarks>
  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 ExecuteDataReader
  93. /// <summary>
  94. /// Executes a single command against a MySQL database, possibly inside an existing transaction.
  95. /// </summary>
  96. /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
  97. /// <param name="transaction"><see cref="MySqlTransaction"/> object to use for the command</param>
  98. /// <param name="commandText">Command text to use</param>
  99. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  100. /// <param name="externalConn">True if the connection should be preserved, false if not</param>
  101. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  102. private static MySqlDataReader ExecuteReader(MySqlConnection connection, MySqlTransaction transaction, string commandText, MySqlParameter[] commandParameters, bool externalConn)
  103. {
  104. //create a command and prepare it for execution
  105. MySqlCommand cmd = new MySqlCommand();
  106. cmd.Connection = connection;
  107. cmd.Transaction = transaction;
  108. cmd.CommandText = commandText;
  109. cmd.CommandType = CommandType.Text;
  110. if (commandParameters != null)
  111. foreach (MySqlParameter p in commandParameters)
  112. cmd.Parameters.Add(p);
  113. //create a reader
  114. MySqlDataReader dr;
  115. // call ExecuteReader with the appropriate CommandBehavior
  116. if (externalConn)
  117. {
  118. dr = cmd.ExecuteReader();
  119. }
  120. else
  121. {
  122. dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
  123. }
  124. // detach the SqlParameters from the command object, so they can be used again.
  125. cmd.Parameters.Clear();
  126. return dr;
  127. }
  128. /// <summary>
  129. /// Executes a single command against a MySQL database.
  130. /// </summary>
  131. /// <param name="connectionString">Settings to use for this command</param>
  132. /// <param name="commandText">Command text to use</param>
  133. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  134. public static MySqlDataReader ExecuteReader(string connectionString, string commandText)
  135. {
  136. //pass through the call providing null for the set of SqlParameters
  137. return ExecuteReader(connectionString, commandText, null);
  138. }
  139. /// <summary>
  140. /// Executes a single command against a MySQL database.
  141. /// </summary>
  142. /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
  143. /// <param name="commandText">Command text to use</param>
  144. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  145. public static MySqlDataReader ExecuteReader(MySqlConnection connection, string commandText)
  146. {
  147. //pass through the call providing null for the set of SqlParameters
  148. return ExecuteReader(connection, null, commandText, null, true);
  149. }
  150. /// <summary>
  151. /// Executes a single command against a MySQL database.
  152. /// </summary>
  153. /// <param name="connectionString">Settings to use for this command</param>
  154. /// <param name="commandText">Command text to use</param>
  155. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  156. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  157. public static MySqlDataReader ExecuteReader(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  158. {
  159. //create & open a SqlConnection
  160. MySqlConnection cn = new MySqlConnection(connectionString);
  161. cn.Open();
  162. //call the private overload that takes an internally owned connection in place of the connection string
  163. return ExecuteReader(cn, null, commandText, commandParameters, false);
  164. }
  165. /// <summary>
  166. /// Executes a single command against a MySQL database.
  167. /// </summary>
  168. /// <param name="connection">Connection to use for the command</param>
  169. /// <param name="commandText">Command text to use</param>
  170. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  171. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  172. public static MySqlDataReader ExecuteReader(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  173. {
  174. //call the private overload that takes an internally owned connection in place of the connection string
  175. return ExecuteReader(connection, null, commandText, commandParameters, true);
  176. }
  177. #endregion
  178. #region ExecuteScalar
  179. /// <summary>
  180. /// Execute a single command against a MySQL database.
  181. /// </summary>
  182. /// <param name="connectionString">Settings to use for the update</param>
  183. /// <param name="commandText">Command text to use for the update</param>
  184. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  185. public static object ExecuteScalar(string connectionString, string commandText)
  186. {
  187. //pass through the call providing null for the set of MySqlParameters
  188. return ExecuteScalar(connectionString, commandText, null);
  189. }
  190. /// <summary>
  191. /// Execute a single command against a MySQL database.
  192. /// </summary>
  193. /// <param name="connectionString">Settings to use for the command</param>
  194. /// <param name="commandText">Command text to use for the command</param>
  195. /// <param name="commandParameters">Parameters to use for the command</param>
  196. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  197. public static object ExecuteScalar(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  198. {
  199. //create & open a SqlConnection, and dispose of it after we are done.
  200. using (MySqlConnection cn = new MySqlConnection(connectionString))
  201. {
  202. cn.Open();
  203. //call the overload that takes a connection in place of the connection string
  204. return ExecuteScalar(cn, commandText, commandParameters);
  205. }
  206. }
  207. /// <summary>
  208. /// Execute a single command against a MySQL database.
  209. /// </summary>
  210. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  211. /// <param name="commandText">Command text to use for the command</param>
  212. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  213. public static object ExecuteScalar(MySqlConnection connection, string commandText)
  214. {
  215. //pass through the call providing null for the set of MySqlParameters
  216. return ExecuteScalar(connection, commandText, null);
  217. }
  218. /// <summary>
  219. /// Execute a single command against a MySQL database.
  220. /// </summary>
  221. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  222. /// <param name="commandText">Command text to use for the command</param>
  223. /// <param name="commandParameters">Parameters to use for the command</param>
  224. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  225. public static object ExecuteScalar(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  226. {
  227. //create a command and prepare it for execution
  228. MySqlCommand cmd = new MySqlCommand();
  229. cmd.Connection = connection;
  230. cmd.CommandText = commandText;
  231. cmd.CommandType = CommandType.Text;
  232. if (commandParameters != null)
  233. foreach (MySqlParameter p in commandParameters)
  234. cmd.Parameters.Add(p);
  235. //execute the command & return the results
  236. object retval = cmd.ExecuteScalar();
  237. // detach the SqlParameters from the command object, so they can be used again.
  238. cmd.Parameters.Clear();
  239. return retval;
  240. }
  241. #endregion
  242. #region Utility methods
  243. private static CharClass[] MakeCharClassArray()
  244. {
  245. CharClass[] a = new CharClass[65536];
  246. foreach (char c in stringOfBackslashChars)
  247. {
  248. a[c] = CharClass.Backslash;
  249. }
  250. foreach (char c in stringOfQuoteChars)
  251. {
  252. a[c] = CharClass.Quote;
  253. }
  254. return a;
  255. }
  256. private static bool NeedsQuoting(string s)
  257. {
  258. return s.Any(c => charClassArray[c] != CharClass.None);
  259. }
  260. /// <summary>
  261. /// Escapes the string.
  262. /// </summary>
  263. /// <param name="value">The string to escape.</param>
  264. /// <returns>The string with all quotes escaped.</returns>
  265. public static string EscapeString(string value)
  266. {
  267. if (!NeedsQuoting(value))
  268. return value;
  269. StringBuilder sb = new StringBuilder();
  270. foreach (char c in value)
  271. {
  272. CharClass charClass = charClassArray[c];
  273. if (charClass != CharClass.None)
  274. {
  275. sb.Append("\\");
  276. }
  277. sb.Append(c);
  278. }
  279. return sb.ToString();
  280. }
  281. /// <summary>
  282. /// Replaces quotes with double quotes.
  283. /// </summary>
  284. /// <param name="value">The string to modidify.</param>
  285. /// <returns>A string containing double quotes instead of single quotes.</returns>
  286. public static string DoubleQuoteString(string value)
  287. {
  288. if (!NeedsQuoting(value))
  289. return value;
  290. StringBuilder sb = new StringBuilder();
  291. foreach (char c in value)
  292. {
  293. CharClass charClass = charClassArray[c];
  294. if (charClass == CharClass.Quote)
  295. sb.Append(c);
  296. else if (charClass == CharClass.Backslash)
  297. sb.Append("\\");
  298. sb.Append(c);
  299. }
  300. return sb.ToString();
  301. }
  302. #endregion
  303. #region Async
  304. #region NonQuery
  305. /// <summary>
  306. /// Async version of ExecuteNonQuery
  307. /// </summary>
  308. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  309. /// <param name="commandText">SQL command to be executed</param>
  310. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command.</param>
  311. /// <returns>Rows affected</returns>
  312. public static Task<int> ExecuteNonQueryAsync(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  313. {
  314. return ExecuteNonQueryAsync(connection, commandText, CancellationToken.None, commandParameters);
  315. }
  316. public static Task<int> ExecuteNonQueryAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  317. {
  318. var result = new TaskCompletionSource<int>();
  319. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  320. {
  321. try
  322. {
  323. var queryResult = ExecuteNonQuery(connection, commandText, commandParameters);
  324. result.SetResult(queryResult);
  325. }
  326. catch (Exception ex)
  327. {
  328. result.SetException(ex);
  329. }
  330. }
  331. else
  332. {
  333. result.SetCanceled();
  334. }
  335. return result.Task;
  336. }
  337. /// <summary>
  338. /// Asynchronous version of the ExecuteNonQuery method.
  339. /// </summary>
  340. /// <param name="connectionString"><see cref="MySqlConnection.ConnectionString"/> to use.</param>
  341. /// <param name="commandText">The SQL command to be executed.</param>
  342. /// <param name="commandParameters">An array of <see cref="MySqlParameter"/> objects to use with the command.</param>
  343. /// <returns>The number of rows affected.</returns>
  344. public static Task<int> ExecuteNonQueryAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  345. {
  346. return ExecuteNonQueryAsync(connectionString, commandText, CancellationToken.None, commandParameters);
  347. }
  348. /// <summary>
  349. /// Asynchronous version of the ExecuteNonQuery method.
  350. /// </summary>
  351. /// <param name="connectionString"><see cref="MySqlConnection.ConnectionString"/> to use.</param>
  352. /// <param name="commandText">The SQL command to be executed.</param>
  353. /// <param name="cancellationToken">The cancellation token.</param>
  354. /// <param name="commandParameters">An array of <see cref="MySqlParameter"/> objects to use with the command.</param>
  355. /// <returns>The number of rows affected.</returns>
  356. public static Task<int> ExecuteNonQueryAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  357. {
  358. var result = new TaskCompletionSource<int>();
  359. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  360. {
  361. try
  362. {
  363. var queryResult = ExecuteNonQuery(connectionString, commandText, commandParameters);
  364. result.SetResult(queryResult);
  365. }
  366. catch (Exception ex)
  367. {
  368. result.SetException(ex);
  369. }
  370. }
  371. else
  372. {
  373. result.SetCanceled();
  374. }
  375. return result.Task;
  376. }
  377. #endregion
  378. #region DataReader
  379. /// <summary>
  380. /// Async version of ExecuteReader
  381. /// </summary>
  382. /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
  383. /// <param name="transaction"><see cref="MySqlTransaction"/> object to use for the command</param>
  384. /// <param name="commandText">Command text to use</param>
  385. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  386. /// <param name="ExternalConn">True if the connection should be preserved, false if not</param>
  387. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  388. private static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, MySqlTransaction transaction, string commandText, MySqlParameter[] commandParameters, bool ExternalConn)
  389. {
  390. return ExecuteReaderAsync(connection, transaction, commandText, commandParameters, ExternalConn, CancellationToken.None);
  391. }
  392. private static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, MySqlTransaction transaction, string commandText, MySqlParameter[] commandParameters, bool ExternalConn, CancellationToken cancellationToken)
  393. {
  394. var result = new TaskCompletionSource<MySqlDataReader>();
  395. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  396. {
  397. try
  398. {
  399. var reader = ExecuteReader(connection, transaction, commandText, commandParameters, ExternalConn);
  400. result.SetResult(reader);
  401. }
  402. catch (Exception ex)
  403. {
  404. result.SetException(ex);
  405. }
  406. }
  407. else
  408. {
  409. result.SetCanceled();
  410. }
  411. return result.Task;
  412. }
  413. /// <summary>
  414. /// Async version of ExecuteReader
  415. /// </summary>
  416. /// <param name="connectionString">Settings to use for this command</param>
  417. /// <param name="commandText">Command text to use</param>
  418. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  419. public static Task<MySqlDataReader> ExecuteReaderAsync(string connectionString, string commandText)
  420. {
  421. return ExecuteReaderAsync(connectionString, commandText, CancellationToken.None, (MySqlParameter[])null);
  422. }
  423. public static Task<MySqlDataReader> ExecuteReaderAsync(string connectionString, string commandText, CancellationToken cancellationToken)
  424. {
  425. return ExecuteReaderAsync(connectionString, commandText, cancellationToken, (MySqlParameter[])null);
  426. }
  427. /// <summary>
  428. /// Async version of ExecuteReader
  429. /// </summary>
  430. /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
  431. /// <param name="commandText">Command text to use</param>
  432. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  433. public static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, string commandText)
  434. {
  435. return ExecuteReaderAsync(connection, null, commandText, (MySqlParameter[])null, true, CancellationToken.None);
  436. }
  437. public static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken)
  438. {
  439. return ExecuteReaderAsync(connection, null, commandText, (MySqlParameter[])null, true, cancellationToken);
  440. }
  441. /// <summary>
  442. /// Async version of ExecuteReader
  443. /// </summary>
  444. /// <param name="connectionString">Settings to use for this command</param>
  445. /// <param name="commandText">Command text to use</param>
  446. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  447. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  448. public static Task<MySqlDataReader> ExecuteReaderAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  449. {
  450. return ExecuteReaderAsync(connectionString, commandText, CancellationToken.None, commandParameters);
  451. }
  452. public static Task<MySqlDataReader> ExecuteReaderAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  453. {
  454. var result = new TaskCompletionSource<MySqlDataReader>();
  455. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  456. {
  457. try
  458. {
  459. var reader = ExecuteReader(connectionString, commandText, commandParameters);
  460. result.SetResult(reader);
  461. }
  462. catch (Exception ex)
  463. {
  464. result.SetException(ex);
  465. }
  466. }
  467. else
  468. {
  469. result.SetCanceled();
  470. }
  471. return result.Task;
  472. }
  473. /// <summary>
  474. /// Async version of ExecuteReader
  475. /// </summary>
  476. /// <param name="connection">Connection to use for the command</param>
  477. /// <param name="commandText">Command text to use</param>
  478. /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
  479. /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
  480. public static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  481. {
  482. return ExecuteReaderAsync(connection, null, commandText, commandParameters, true, CancellationToken.None);
  483. }
  484. public static Task<MySqlDataReader> ExecuteReaderAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  485. {
  486. return ExecuteReaderAsync(connection, null, commandText, commandParameters, true, cancellationToken);
  487. }
  488. #endregion
  489. #region Scalar
  490. /// <summary>
  491. /// Async version of ExecuteScalar
  492. /// </summary>
  493. /// <param name="connectionString">Settings to use for the update</param>
  494. /// <param name="commandText">Command text to use for the update</param>
  495. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  496. public static Task<object> ExecuteScalarAsync(string connectionString, string commandText)
  497. {
  498. return ExecuteScalarAsync(connectionString, commandText, CancellationToken.None, (MySqlParameter[])null);
  499. }
  500. public static Task<object> ExecuteScalarAsync(string connectionString, string commandText, CancellationToken cancellationToken)
  501. {
  502. return ExecuteScalarAsync(connectionString, commandText, cancellationToken, (MySqlParameter[])null);
  503. }
  504. /// <summary>
  505. /// Async version of ExecuteScalar
  506. /// </summary>
  507. /// <param name="connectionString">Settings to use for the command</param>
  508. /// <param name="commandText">Command text to use for the command</param>
  509. /// <param name="commandParameters">Parameters to use for the command</param>
  510. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  511. public static Task<object> ExecuteScalarAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters)
  512. {
  513. return ExecuteScalarAsync(connectionString, commandText, CancellationToken.None, commandParameters);
  514. }
  515. public static Task<object> ExecuteScalarAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  516. {
  517. var result = new TaskCompletionSource<object>();
  518. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  519. {
  520. try
  521. {
  522. var scalarResult = ExecuteScalar(connectionString, commandText, commandParameters);
  523. result.SetResult(scalarResult);
  524. }
  525. catch (Exception ex)
  526. {
  527. result.SetException(ex);
  528. }
  529. }
  530. else
  531. {
  532. result.SetCanceled();
  533. }
  534. return result.Task;
  535. }
  536. /// <summary>
  537. /// Async version of ExecuteScalar
  538. /// </summary>
  539. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  540. /// <param name="commandText">Command text to use for the command</param>
  541. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  542. public static Task<object> ExecuteScalarAsync(MySqlConnection connection, string commandText)
  543. {
  544. return ExecuteScalarAsync(connection, commandText, CancellationToken.None, (MySqlParameter[])null);
  545. }
  546. public static Task<object> ExecuteScalarAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken)
  547. {
  548. return ExecuteScalarAsync(connection, commandText, cancellationToken, (MySqlParameter[])null);
  549. }
  550. /// <summary>
  551. /// Async version of ExecuteScalar
  552. /// </summary>
  553. /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
  554. /// <param name="commandText">Command text to use for the command</param>
  555. /// <param name="commandParameters">Parameters to use for the command</param>
  556. /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
  557. public static Task<object> ExecuteScalarAsync(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
  558. {
  559. return ExecuteScalarAsync(connection, commandText, CancellationToken.None, commandParameters);
  560. }
  561. public static Task<object> ExecuteScalarAsync(MySqlConnection connection, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters)
  562. {
  563. var result = new TaskCompletionSource<object>();
  564. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  565. {
  566. try
  567. {
  568. var scalarResult = ExecuteScalar(connection, commandText, commandParameters);
  569. result.SetResult(scalarResult);
  570. }
  571. catch (Exception ex)
  572. {
  573. result.SetException(ex);
  574. }
  575. }
  576. else
  577. {
  578. result.SetCanceled();
  579. }
  580. return result.Task;
  581. }
  582. #endregion
  583. #endregion
  584. }
  585. }
  586. #endif