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.

1204 lines
48 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.Data.Common;
  26. using System.ComponentModel;
  27. using System.Collections.Generic;
  28. using System.Threading.Tasks;
  29. using System.Threading;
  30. using System.Drawing;
  31. namespace Externals.MySql.Data.MySqlClient
  32. {
  33. [DesignerCategory("Code")]
  34. [Designer("Externals.MySql.Data.MySqlClient.Design.MySqlDataAdapterDesigner,MySqlClient.Design")]
  35. internal sealed class MySqlDataAdapter : DbDataAdapter, IDbDataAdapter, IDataAdapter
  36. {
  37. private bool loadingDefaults;
  38. private int updateBatchSize;
  39. List<IDbCommand> commandBatch;
  40. /// <summary>
  41. /// Occurs during Update before a command is executed against the data source. The attempt to update is made, so the event fires.
  42. /// </summary>
  43. public event MySqlRowUpdatingEventHandler RowUpdating;
  44. /// <summary>
  45. /// Occurs during Update after a command is executed against the data source. The attempt to update is made, so the event fires.
  46. /// </summary>
  47. public event MySqlRowUpdatedEventHandler RowUpdated;
  48. public MySqlDataAdapter()
  49. {
  50. loadingDefaults = true;
  51. updateBatchSize = 1;
  52. }
  53. public MySqlDataAdapter(MySqlCommand selectCommand)
  54. : this()
  55. {
  56. SelectCommand = selectCommand;
  57. }
  58. public MySqlDataAdapter(string selectCommandText, MySqlConnection connection)
  59. : this()
  60. {
  61. SelectCommand = new MySqlCommand(selectCommandText, connection);
  62. }
  63. public MySqlDataAdapter(string selectCommandText, string selectConnString)
  64. : this()
  65. {
  66. SelectCommand = new MySqlCommand(selectCommandText,
  67. new MySqlConnection(selectConnString));
  68. }
  69. #region Properties
  70. [Description("Used during Update for deleted rows in Dataset.")]
  71. public new MySqlCommand DeleteCommand
  72. {
  73. get { return (MySqlCommand)base.DeleteCommand; }
  74. set { base.DeleteCommand = value; }
  75. }
  76. [Description("Used during Update for new rows in Dataset.")]
  77. public new MySqlCommand InsertCommand
  78. {
  79. get { return (MySqlCommand)base.InsertCommand; }
  80. set { base.InsertCommand = value; }
  81. }
  82. [Description("Used during Fill/FillSchema")]
  83. [Category("Fill")]
  84. public new MySqlCommand SelectCommand
  85. {
  86. get { return (MySqlCommand)base.SelectCommand; }
  87. set { base.SelectCommand = value; }
  88. }
  89. [Description("Used during Update for modified rows in Dataset.")]
  90. public new MySqlCommand UpdateCommand
  91. {
  92. get { return (MySqlCommand)base.UpdateCommand; }
  93. set { base.UpdateCommand = value; }
  94. }
  95. internal bool LoadDefaults
  96. {
  97. get { return loadingDefaults; }
  98. set { loadingDefaults = value; }
  99. }
  100. #endregion
  101. /// <summary>
  102. /// Open connection if it was closed.
  103. /// Necessary to workaround "connection must be open and valid" error
  104. /// with batched updates.
  105. /// </summary>
  106. /// <param name="state">Row state</param>
  107. /// <param name="openedConnections"> list of opened connections
  108. /// If connection is opened by this function, the list is updated
  109. /// </param>
  110. /// <returns>true if connection was opened</returns>
  111. private void OpenConnectionIfClosed(DataRowState state,
  112. List<MySqlConnection> openedConnections)
  113. {
  114. MySqlCommand cmd = null;
  115. switch (state)
  116. {
  117. case DataRowState.Added:
  118. cmd = InsertCommand;
  119. break;
  120. case DataRowState.Deleted:
  121. cmd = DeleteCommand;
  122. break;
  123. case DataRowState.Modified:
  124. cmd = UpdateCommand;
  125. break;
  126. default:
  127. return;
  128. }
  129. if (cmd != null && cmd.Connection != null &&
  130. cmd.Connection.connectionState == ConnectionState.Closed)
  131. {
  132. cmd.Connection.Open();
  133. openedConnections.Add(cmd.Connection);
  134. }
  135. }
  136. protected override int Update(DataRow[] dataRows, DataTableMapping tableMapping)
  137. {
  138. List<MySqlConnection> connectionsOpened = new List<MySqlConnection>();
  139. try
  140. {
  141. // Open connections for insert/update/update commands, if
  142. // connections are closed.
  143. foreach (DataRow row in dataRows)
  144. {
  145. OpenConnectionIfClosed(row.RowState, connectionsOpened);
  146. }
  147. int ret = base.Update(dataRows, tableMapping);
  148. return ret;
  149. }
  150. finally
  151. {
  152. foreach (MySqlConnection c in connectionsOpened)
  153. c.Close();
  154. }
  155. }
  156. #region Batching Support
  157. public override int UpdateBatchSize
  158. {
  159. get { return updateBatchSize; }
  160. set { updateBatchSize = value; }
  161. }
  162. protected override void InitializeBatching()
  163. {
  164. commandBatch = new List<IDbCommand>();
  165. }
  166. protected override int AddToBatch(IDbCommand command)
  167. {
  168. // the first time each command is asked to be batched, we ask
  169. // that command to prepare its batchable command text. We only want
  170. // to do this one time for each command
  171. MySqlCommand commandToBatch = (MySqlCommand)command;
  172. if (commandToBatch.BatchableCommandText == null)
  173. commandToBatch.GetCommandTextForBatching();
  174. IDbCommand cloneCommand = (IDbCommand)((ICloneable)command).Clone();
  175. commandBatch.Add(cloneCommand);
  176. return commandBatch.Count - 1;
  177. }
  178. protected override int ExecuteBatch()
  179. {
  180. int recordsAffected = 0;
  181. int index = 0;
  182. while (index < commandBatch.Count)
  183. {
  184. MySqlCommand cmd = (MySqlCommand)commandBatch[index++];
  185. for (int index2 = index; index2 < commandBatch.Count; index2++, index++)
  186. {
  187. MySqlCommand cmd2 = (MySqlCommand)commandBatch[index2];
  188. if (cmd2.BatchableCommandText == null ||
  189. cmd2.CommandText != cmd.CommandText) break;
  190. cmd.AddToBatch(cmd2);
  191. }
  192. recordsAffected += cmd.ExecuteNonQuery();
  193. }
  194. return recordsAffected;
  195. }
  196. protected override void ClearBatch()
  197. {
  198. if (commandBatch.Count > 0)
  199. {
  200. MySqlCommand cmd = (MySqlCommand)commandBatch[0];
  201. if (cmd.Batch != null)
  202. cmd.Batch.Clear();
  203. }
  204. commandBatch.Clear();
  205. }
  206. protected override void TerminateBatching()
  207. {
  208. ClearBatch();
  209. commandBatch = null;
  210. }
  211. protected override IDataParameter GetBatchedParameter(int commandIdentifier, int parameterIndex)
  212. {
  213. return (IDataParameter)commandBatch[commandIdentifier].Parameters[parameterIndex];
  214. }
  215. #endregion
  216. /// <summary>
  217. /// Overridden. See <see cref="DbDataAdapter.CreateRowUpdatedEvent"/>.
  218. /// </summary>
  219. /// <param name="dataRow"></param>
  220. /// <param name="command"></param>
  221. /// <param name="statementType"></param>
  222. /// <param name="tableMapping"></param>
  223. /// <returns></returns>
  224. override protected RowUpdatedEventArgs CreateRowUpdatedEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
  225. {
  226. return new MySqlRowUpdatedEventArgs(dataRow, command, statementType, tableMapping);
  227. }
  228. /// <summary>
  229. /// Overridden. See <see cref="DbDataAdapter.CreateRowUpdatingEvent"/>.
  230. /// </summary>
  231. /// <param name="dataRow"></param>
  232. /// <param name="command"></param>
  233. /// <param name="statementType"></param>
  234. /// <param name="tableMapping"></param>
  235. /// <returns></returns>
  236. override protected RowUpdatingEventArgs CreateRowUpdatingEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
  237. {
  238. return new MySqlRowUpdatingEventArgs(dataRow, command, statementType, tableMapping);
  239. }
  240. /// <summary>
  241. /// Overridden. Raises the RowUpdating event.
  242. /// </summary>
  243. /// <param name="value">A MySqlRowUpdatingEventArgs that contains the event data.</param>
  244. override protected void OnRowUpdating(RowUpdatingEventArgs value)
  245. {
  246. if (RowUpdating != null)
  247. RowUpdating(this, (value as MySqlRowUpdatingEventArgs));
  248. }
  249. /// <summary>
  250. /// Overridden. Raises the RowUpdated event.
  251. /// </summary>
  252. /// <param name="value">A MySqlRowUpdatedEventArgs that contains the event data. </param>
  253. override protected void OnRowUpdated(RowUpdatedEventArgs value)
  254. {
  255. if (RowUpdated != null)
  256. RowUpdated(this, (value as MySqlRowUpdatedEventArgs));
  257. }
  258. #region Async
  259. #region Fill
  260. /// <summary>
  261. /// Asynchronous version of the Fill method.
  262. /// </summary>
  263. /// <param name="dataSet">The <see cref="DataSet"/> to fill records with.</param>
  264. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataSet"/>.</returns>
  265. public Task<int> FillAsync(DataSet dataSet)
  266. {
  267. return FillAsync(dataSet, CancellationToken.None);
  268. }
  269. /// <summary>
  270. /// Asynchronous version of the Fill method.
  271. /// </summary>
  272. /// <param name="dataSet">The <see cref="DataSet"/> to fill records with.</param>
  273. /// <param name="cancellationToken">The cancellation token.</param>
  274. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataSet"/>.</returns>
  275. public Task<int> FillAsync(DataSet dataSet, CancellationToken cancellationToken)
  276. {
  277. var result = new TaskCompletionSource<int>();
  278. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  279. {
  280. try
  281. {
  282. var fillResult = base.Fill(dataSet);
  283. result.SetResult(fillResult);
  284. }
  285. catch (Exception ex)
  286. {
  287. result.SetException(ex);
  288. }
  289. }
  290. else
  291. {
  292. result.SetCanceled();
  293. }
  294. return result.Task;
  295. }
  296. /// <summary>
  297. /// Asynchronous version of the Fill method.
  298. /// </summary>
  299. /// <param name="dataTable">The name of the <see cref="DataTable"/> to use for table mapping.</param>
  300. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  301. public Task<int> FillAsync(DataTable dataTable)
  302. {
  303. return FillAsync(dataTable, CancellationToken.None);
  304. }
  305. /// <summary>
  306. /// Asynchronous version of the Fill method.
  307. /// </summary>
  308. /// <param name="dataTable">The name of the <see cref="DataTable"/> to use for table mapping.</param>
  309. /// <param name="cancellationToken">The cancellation token.</param>
  310. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  311. public Task<int> FillAsync(DataTable dataTable, CancellationToken cancellationToken)
  312. {
  313. var result = new TaskCompletionSource<int>();
  314. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  315. {
  316. try
  317. {
  318. var fillResult = base.Fill(dataTable);
  319. result.SetResult(fillResult);
  320. }
  321. catch (Exception ex)
  322. {
  323. result.SetException(ex);
  324. }
  325. }
  326. else
  327. {
  328. result.SetCanceled();
  329. }
  330. return result.Task;
  331. }
  332. /// <summary>
  333. /// Asynchronous version of the Fill method.
  334. /// </summary>
  335. /// <param name="dataSet">The <see cref="DataSet"/> to fill with records.</param>
  336. /// <param name="srcTable">The name of the source table to use for table mapping.</param>
  337. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataSet"/>.</returns>
  338. public Task<int> FillAsync(DataSet dataSet, string srcTable)
  339. {
  340. return FillAsync(dataSet, srcTable, CancellationToken.None);
  341. }
  342. /// <summary>
  343. /// Asynchronous version of the Fill method.
  344. /// </summary>
  345. /// <param name="dataSet">The <see cref="DataSet"/> to fill with records.</param>
  346. /// <param name="srcTable">The name of the source table to use for table mapping.</param>
  347. /// <param name="cancellationToken">The cancellation token.</param>
  348. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataSet"/>.</returns>
  349. public Task<int> FillAsync(DataSet dataSet, string srcTable, CancellationToken cancellationToken)
  350. {
  351. var result = new TaskCompletionSource<int>();
  352. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  353. {
  354. try
  355. {
  356. var fillResult = base.Fill(dataSet, srcTable);
  357. result.SetResult(fillResult);
  358. }
  359. catch (Exception ex)
  360. {
  361. result.SetException(ex);
  362. }
  363. }
  364. else
  365. {
  366. result.SetCanceled();
  367. }
  368. return result.Task;
  369. }
  370. /// <summary>
  371. /// Asynchronous version of the Fill method.
  372. /// </summary>
  373. /// <param name="dataTable">The <see cref="DataTable"/> to fill with records.</param>
  374. /// <param name="dataReader">An instance of <see cref="IDataReader"/>.</param>
  375. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  376. public Task<int> FillAsync(DataTable dataTable, IDataReader dataReader)
  377. {
  378. return FillAsync(dataTable, dataReader, CancellationToken.None);
  379. }
  380. /// <summary>
  381. /// Asynchronous version of the Fill method.
  382. /// </summary>
  383. /// <param name="dataTable">The <see cref="DataTable"/> to fill with records.</param>
  384. /// <param name="dataReader">An instance of <see cref="IDataReader"/>.</param>
  385. /// <param name="cancellationToken">The cancellation token.</param>
  386. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  387. public Task<int> FillAsync(DataTable dataTable, IDataReader dataReader, CancellationToken cancellationToken)
  388. {
  389. var result = new TaskCompletionSource<int>();
  390. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  391. {
  392. try
  393. {
  394. var fillResult = base.Fill(dataTable, dataReader);
  395. result.SetResult(fillResult);
  396. }
  397. catch (Exception ex)
  398. {
  399. result.SetException(ex);
  400. }
  401. }
  402. else
  403. {
  404. result.SetCanceled();
  405. }
  406. return result.Task;
  407. }
  408. /// <summary>
  409. /// Asynchronous version of the Fill method.
  410. /// </summary>
  411. /// <param name="dataTable">The <see cref="DataTable"/> to fill with records.</param>
  412. /// <param name="command">The SQL SELECT statement used to retrieve rows from the data source.</param>
  413. /// <param name="behavior">One of the <see cref="CommandBehavior"/> values.</param>
  414. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  415. public Task<int> FillAsync(DataTable dataTable, IDbCommand command, CommandBehavior behavior)
  416. {
  417. return FillAsync(dataTable, command, behavior, CancellationToken.None);
  418. }
  419. /// <summary>
  420. /// Asynchronous version of the Fill method.
  421. /// </summary>
  422. /// <param name="dataTable">The <see cref="DataTable"/> to fill with records.</param>
  423. /// <param name="command">The SQL SELECT statement used to retrieve rows from the data source.</param>
  424. /// <param name="behavior">One of the <see cref="CommandBehavior"/> values.</param>
  425. /// <param name="cancellationToken">The cancellation token.</param>
  426. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  427. public Task<int> FillAsync(DataTable dataTable, IDbCommand command, CommandBehavior behavior, CancellationToken cancellationToken)
  428. {
  429. var result = new TaskCompletionSource<int>();
  430. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  431. {
  432. try
  433. {
  434. var fillResult = base.Fill(dataTable, command, behavior);
  435. result.SetResult(fillResult);
  436. }
  437. catch (Exception ex)
  438. {
  439. result.SetException(ex);
  440. }
  441. }
  442. else
  443. {
  444. result.SetCanceled();
  445. }
  446. return result.Task;
  447. }
  448. /// <summary>
  449. /// Asynchronous version of the Fill method.
  450. /// </summary>
  451. /// <param name="startRecord">The start record.</param>
  452. /// <param name="maxRecords">The max number of affected records.</param>
  453. /// <param name="dataTables">The <see cref="DataTable"/>s to fill with records.</param>
  454. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  455. public Task<int> FillAsync(int startRecord, int maxRecords, params DataTable[] dataTables)
  456. {
  457. return FillAsync(startRecord, maxRecords, CancellationToken.None, dataTables);
  458. }
  459. /// <summary>
  460. /// Asynchronous version of the Fill method.
  461. /// </summary>
  462. /// <param name="startRecord">The start record.</param>
  463. /// <param name="maxRecords">The max number of affected records.</param>
  464. /// <param name="cancellationToken">The cancellation token.</param>
  465. /// <param name="dataTables">The <see cref="DataTable"/>s to fill with records.</param>
  466. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  467. public Task<int> FillAsync(int startRecord, int maxRecords, CancellationToken cancellationToken, params DataTable[] dataTables)
  468. {
  469. var result = new TaskCompletionSource<int>();
  470. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  471. {
  472. try
  473. {
  474. var fillResult = base.Fill(startRecord, maxRecords, dataTables);
  475. result.SetResult(fillResult);
  476. }
  477. catch (Exception ex)
  478. {
  479. result.SetException(ex);
  480. }
  481. }
  482. else
  483. {
  484. result.SetCanceled();
  485. }
  486. return result.Task;
  487. }
  488. /// <summary>
  489. /// Asynchronous version of the Fill method.
  490. /// </summary>
  491. /// <param name="dataSet">The <see cref="DataSet"/> to fill with records.</param>
  492. /// <param name="startRecord">The start record.</param>
  493. /// <param name="maxRecords">The max number of affected records.</param>
  494. /// <param name="srcTable">The name of the source table to use for table mapping.</param>
  495. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataSet"/>.</returns>
  496. public Task<int> FillAsync(DataSet dataSet, int startRecord, int maxRecords, string srcTable)
  497. {
  498. return FillAsync(dataSet, startRecord, maxRecords, srcTable, CancellationToken.None);
  499. }
  500. /// <summary>
  501. /// Asynchronous version of the Fill method.
  502. /// </summary>
  503. /// <param name="dataSet">The <see cref="DataSet"/> to fill with records.</param>
  504. /// <param name="startRecord">The start record.</param>
  505. /// <param name="maxRecords">The max number of affected records.</param>
  506. /// <param name="srcTable">The name of the source table to use for table mapping.</param>
  507. /// <param name="cancellationToken">The cancellation token.</param>
  508. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataSet"/>.</returns>
  509. public Task<int> FillAsync(DataSet dataSet, int startRecord, int maxRecords, string srcTable, CancellationToken cancellationToken)
  510. {
  511. var result = new TaskCompletionSource<int>();
  512. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  513. {
  514. try
  515. {
  516. var fillResult = base.Fill(dataSet, startRecord, maxRecords, srcTable);
  517. result.SetResult(fillResult);
  518. }
  519. catch (Exception ex)
  520. {
  521. result.SetException(ex);
  522. }
  523. }
  524. else
  525. {
  526. result.SetCanceled();
  527. }
  528. return result.Task;
  529. }
  530. /// <summary>
  531. /// Asynchronous version of the Fill method.
  532. /// </summary>
  533. /// <param name="dataSet">The <see cref="DataSet"/> to fill with records.</param>
  534. /// <param name="srcTable">The name of the source table to use for table mapping.</param>
  535. /// <param name="dataReader">An instance of <see cref="IDataReader"/>.</param>
  536. /// <param name="startRecord">The start record.</param>
  537. /// <param name="maxRecords">The max number of affected records.</param>
  538. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataSet"/>.</returns>
  539. public Task<int> FillAsync(DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords)
  540. {
  541. return FillAsync(dataSet, srcTable, dataReader, startRecord, maxRecords, CancellationToken.None);
  542. }
  543. /// <summary>
  544. /// Asynchronous version of the Fill method.
  545. /// </summary>
  546. /// <param name="dataSet">The <see cref="DataSet"/> to fill with records.</param>
  547. /// <param name="srcTable">The name of the source table to use for table mapping.</param>
  548. /// <param name="dataReader">An instance of <see cref="IDataReader"/>.</param>
  549. /// <param name="startRecord">The start record.</param>
  550. /// <param name="maxRecords">The max number of affected records.</param>
  551. /// <param name="cancellationToken">The cancellation token.</param>
  552. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataSet"/>.</returns>
  553. public Task<int> FillAsync(DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords, CancellationToken cancellationToken)
  554. {
  555. var result = new TaskCompletionSource<int>();
  556. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  557. {
  558. try
  559. {
  560. var fillResult = base.Fill(dataSet, srcTable, dataReader, startRecord, maxRecords);
  561. result.SetResult(fillResult);
  562. }
  563. catch (Exception ex)
  564. {
  565. result.SetException(ex);
  566. }
  567. }
  568. else
  569. {
  570. result.SetCanceled();
  571. }
  572. return result.Task;
  573. }
  574. /// <summary>
  575. /// Asynchronous version of the Fill method.
  576. /// </summary>
  577. /// <param name="dataTables">The <see cref="DataTable"/>s to fill with records.</param>
  578. /// <param name="startRecord">The start record.</param>
  579. /// <param name="maxRecords">The max number of affected records.</param>
  580. /// <param name="command">The SQL SELECT statement used to retrieve rows from the data source.</param>
  581. /// <param name="behavior">One of the <see cref="CommandBehavior"/> values.</param>
  582. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>s.</returns>
  583. public Task<int> FillAsync(DataTable[] dataTables, int startRecord, int maxRecords, IDbCommand command, CommandBehavior behavior)
  584. {
  585. return FillAsync(dataTables, startRecord, maxRecords, command, behavior, CancellationToken.None);
  586. }
  587. /// <summary>
  588. /// Asynchronous version of the Fill method.
  589. /// </summary>
  590. /// <param name="dataTables">The <see cref="DataTable"/>s to fill with records.</param>
  591. /// <param name="startRecord">The start record.</param>
  592. /// <param name="maxRecords">The max number of affected records.</param>
  593. /// <param name="command">The SQL SELECT statement used to retrieve rows from the data source.</param>
  594. /// <param name="behavior">One of the <see cref="CommandBehavior"/> values.</param>
  595. /// <param name="cancellationToken">The cancellation token.</param>
  596. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>s.</returns>
  597. public Task<int> FillAsync(DataTable[] dataTables, int startRecord, int maxRecords, IDbCommand command, CommandBehavior behavior, CancellationToken cancellationToken)
  598. {
  599. var result = new TaskCompletionSource<int>();
  600. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  601. {
  602. try
  603. {
  604. var fillResult = base.Fill(dataTables, startRecord, maxRecords, command, behavior);
  605. result.SetResult(fillResult);
  606. }
  607. catch (Exception ex)
  608. {
  609. result.SetException(ex);
  610. }
  611. }
  612. else
  613. {
  614. result.SetCanceled();
  615. }
  616. return result.Task;
  617. }
  618. /// <summary>
  619. /// Asynchronous version of the Fill method.
  620. /// </summary>
  621. /// <param name="dataSet">The <see cref="DataSet"/> to fill with records.</param>
  622. /// <param name="startRecord">The start record.</param>
  623. /// <param name="maxRecords">The max number of affected records.</param>
  624. /// <param name="srcTable">The name of the source table to use for table mapping.</param>
  625. /// <param name="command">The SQL SELECT statement used to retrieve rows from the data source.</param>
  626. /// <param name="behavior">One of the <see cref="CommandBehavior"/> values.</param>
  627. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  628. public Task<int> FillAsync(DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)
  629. {
  630. return FillAsync(dataSet, startRecord, maxRecords, srcTable, command, behavior, CancellationToken.None);
  631. }
  632. /// <summary>
  633. /// Asynchronous version of the Fill method.
  634. /// </summary>
  635. /// <param name="dataSet">The <see cref="DataSet"/> to fill with records.</param>
  636. /// <param name="startRecord">The start record.</param>
  637. /// <param name="maxRecords">The max number of affected records.</param>
  638. /// <param name="srcTable">The name of the source table to use for table mapping.</param>
  639. /// <param name="command">The SQL SELECT statement used to retrieve rows from the data source.</param>
  640. /// <param name="behavior">One of the <see cref="CommandBehavior"/> values.</param>
  641. /// <param name="cancellationToken">The cancellation token.</param>
  642. /// <returns>The number of rows successfully added to or refreshed in the <see cref="DataTable"/>.</returns>
  643. public Task<int> FillAsync(DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior, CancellationToken cancellationToken)
  644. {
  645. var result = new TaskCompletionSource<int>();
  646. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  647. {
  648. try
  649. {
  650. var fillResult = base.Fill(dataSet, startRecord, maxRecords, srcTable, command, behavior);
  651. result.SetResult(fillResult);
  652. }
  653. catch (Exception ex)
  654. {
  655. result.SetException(ex);
  656. }
  657. }
  658. else
  659. {
  660. result.SetCanceled();
  661. }
  662. return result.Task;
  663. }
  664. #endregion
  665. #region FillSchema
  666. /// <summary>
  667. /// Async version of FillSchema
  668. /// </summary>
  669. /// <param name="dataSet">DataSet to use</param>
  670. /// <param name="schemaType">Schema Type</param>
  671. /// <returns>DataTable[]</returns>
  672. public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType)
  673. {
  674. return FillSchemaAsync(dataSet, schemaType, CancellationToken.None);
  675. }
  676. public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, CancellationToken cancellationToken)
  677. {
  678. var result = new TaskCompletionSource<DataTable[]>();
  679. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  680. {
  681. try
  682. {
  683. var schemaResult = base.FillSchema(dataSet, schemaType);
  684. result.SetResult(schemaResult);
  685. }
  686. catch (Exception ex)
  687. {
  688. result.SetException(ex);
  689. }
  690. }
  691. else
  692. {
  693. result.SetCanceled();
  694. }
  695. return result.Task;
  696. }
  697. /// <summary>
  698. /// Async version of FillSchema
  699. /// </summary>
  700. /// <param name="dataSet">DataSet to use</param>
  701. /// <param name="schemaType">Schema Type</param>
  702. /// <param name="srcTable">Source Table</param>
  703. /// <returns>DataTable[]</returns>
  704. public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, string srcTable)
  705. {
  706. return FillSchemaAsync(dataSet, schemaType, srcTable, CancellationToken.None);
  707. }
  708. public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, string srcTable, CancellationToken cancellationToken)
  709. {
  710. var result = new TaskCompletionSource<DataTable[]>();
  711. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  712. {
  713. try
  714. {
  715. var schemaResult = base.FillSchema(dataSet, schemaType, srcTable);
  716. result.SetResult(schemaResult);
  717. }
  718. catch (Exception ex)
  719. {
  720. result.SetException(ex);
  721. }
  722. }
  723. else
  724. {
  725. result.SetCanceled();
  726. }
  727. return result.Task;
  728. }
  729. /// <summary>
  730. /// Async version of FillSchema
  731. /// </summary>
  732. /// <param name="dataSet">DataSet to use</param>
  733. /// <param name="schemaType">Schema Type</param>
  734. /// <param name="srcTable">Source Table</param>
  735. /// <param name="dataReader">DataReader to use</param>
  736. /// <returns>DataTable[]</returns>
  737. public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, string srcTable, IDataReader dataReader)
  738. {
  739. return FillSchemaAsync(dataSet, schemaType, srcTable, dataReader, CancellationToken.None);
  740. }
  741. public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, string srcTable, IDataReader dataReader, CancellationToken cancellationToken)
  742. {
  743. var result = new TaskCompletionSource<DataTable[]>();
  744. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  745. {
  746. try
  747. {
  748. var schemaResult = base.FillSchema(dataSet, schemaType, srcTable, dataReader);
  749. result.SetResult(schemaResult);
  750. }
  751. catch (Exception ex)
  752. {
  753. result.SetException(ex);
  754. }
  755. }
  756. else
  757. {
  758. result.SetCanceled();
  759. }
  760. return result.Task;
  761. }
  762. /// <summary>
  763. /// Async version of FillSchema
  764. /// </summary>
  765. /// <param name="dataSet">DataSet to use</param>
  766. /// <param name="schemaType">Schema Type</param>
  767. /// <param name="command">DBCommand to use</param>
  768. /// <param name="srcTable">Source Table</param>
  769. /// <param name="behavior">Command Behavior</param>
  770. /// <returns>DataTable[]</returns>
  771. public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, IDbCommand command, string srcTable, CommandBehavior behavior)
  772. {
  773. return FillSchemaAsync(dataSet, schemaType, command, srcTable, behavior, CancellationToken.None);
  774. }
  775. public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, IDbCommand command, string srcTable, CommandBehavior behavior, CancellationToken cancellationToken)
  776. {
  777. var result = new TaskCompletionSource<DataTable[]>();
  778. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  779. {
  780. try
  781. {
  782. var schemaResult = base.FillSchema(dataSet, schemaType, command, srcTable, behavior);
  783. result.SetResult(schemaResult);
  784. }
  785. catch (Exception ex)
  786. {
  787. result.SetException(ex);
  788. }
  789. }
  790. else
  791. {
  792. result.SetCanceled();
  793. }
  794. return result.Task;
  795. }
  796. /// <summary>
  797. /// Async version of FillSchema
  798. /// </summary>
  799. /// <param name="dataTable">DataTable to use</param>
  800. /// <param name="schemaType">Schema Type</param>
  801. /// <returns>DataTable</returns>
  802. public Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType)
  803. {
  804. return FillSchemaAsync(dataTable, schemaType, CancellationToken.None);
  805. }
  806. public Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType, CancellationToken cancellationToken)
  807. {
  808. var result = new TaskCompletionSource<DataTable>();
  809. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  810. {
  811. try
  812. {
  813. var schemaResult = base.FillSchema(dataTable, schemaType);
  814. result.SetResult(schemaResult);
  815. }
  816. catch (Exception ex)
  817. {
  818. result.SetException(ex);
  819. }
  820. }
  821. else
  822. {
  823. result.SetCanceled();
  824. }
  825. return result.Task;
  826. }
  827. /// <summary>
  828. /// Async version of FillSchema
  829. /// </summary>
  830. /// <param name="dataTable">DataTable to use</param>
  831. /// <param name="schemaType">Schema Type</param>
  832. /// <param name="dataReader">DataReader to use</param>
  833. /// <returns>DataTable</returns>
  834. public Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType, IDataReader dataReader)
  835. {
  836. return FillSchemaAsync(dataTable, schemaType, dataReader, CancellationToken.None);
  837. }
  838. public Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType, IDataReader dataReader, CancellationToken cancellationToken)
  839. {
  840. var result = new TaskCompletionSource<DataTable>();
  841. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  842. {
  843. try
  844. {
  845. var schemaResult = base.FillSchema(dataTable, schemaType, dataReader);
  846. result.SetResult(schemaResult);
  847. }
  848. catch (Exception ex)
  849. {
  850. result.SetException(ex);
  851. }
  852. }
  853. else
  854. {
  855. result.SetCanceled();
  856. }
  857. return result.Task;
  858. }
  859. /// <summary>
  860. /// Async version of FillSchema
  861. /// </summary>
  862. /// <param name="dataTable">DataTable to use</param>
  863. /// <param name="schemaType">Schema Type</param>
  864. /// <param name="command">DBCommand to use</param>
  865. /// <param name="behavior">Command Behavior</param>
  866. /// <returns>DataTable</returns>
  867. public Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior)
  868. {
  869. return FillSchemaAsync(dataTable, schemaType, command, behavior, CancellationToken.None);
  870. }
  871. public Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior, CancellationToken cancellationToken)
  872. {
  873. var result = new TaskCompletionSource<DataTable>();
  874. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  875. {
  876. try
  877. {
  878. var schemaResult = base.FillSchema(dataTable, schemaType, command, behavior);
  879. result.SetResult(schemaResult);
  880. }
  881. catch (Exception ex)
  882. {
  883. result.SetException(ex);
  884. }
  885. }
  886. else
  887. {
  888. result.SetCanceled();
  889. }
  890. return result.Task;
  891. }
  892. #endregion
  893. #region Update
  894. /// <summary>
  895. /// Async version of Update
  896. /// </summary>
  897. /// <param name="dataRows">DataRow[] to use</param>
  898. /// <returns>int</returns>
  899. public Task<int> UpdateAsync(DataRow[] dataRows)
  900. {
  901. return UpdateAsync(dataRows, CancellationToken.None);
  902. }
  903. public Task<int> UpdateAsync(DataRow[] dataRows, CancellationToken cancellationToken)
  904. {
  905. var result = new TaskCompletionSource<int>();
  906. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  907. {
  908. try
  909. {
  910. var update = base.Update(dataRows);
  911. result.SetResult(update);
  912. }
  913. catch (Exception ex)
  914. {
  915. result.SetException(ex);
  916. }
  917. }
  918. else
  919. {
  920. result.SetCanceled();
  921. }
  922. return result.Task;
  923. }
  924. /// <summary>
  925. /// Async version of Update
  926. /// </summary>
  927. /// <param name="dataSet">DataSet to use</param>
  928. /// <returns>int</returns>
  929. public Task<int> UpdateAsync(DataSet dataSet)
  930. {
  931. return UpdateAsync(dataSet, CancellationToken.None);
  932. }
  933. public Task<int> UpdateAsync(DataSet dataSet, CancellationToken cancellationToken)
  934. {
  935. var result = new TaskCompletionSource<int>();
  936. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  937. {
  938. try
  939. {
  940. var update = base.Update(dataSet);
  941. result.SetResult(update);
  942. }
  943. catch (Exception ex)
  944. {
  945. result.SetException(ex);
  946. }
  947. }
  948. else
  949. {
  950. result.SetCanceled();
  951. }
  952. return result.Task;
  953. }
  954. /// <summary>
  955. /// Async version of Update
  956. /// </summary>
  957. /// <param name="dataTable">DataTable to use</param>
  958. /// <returns>int</returns>
  959. public Task<int> UpdateAsync(DataTable dataTable)
  960. {
  961. return UpdateAsync(dataTable, CancellationToken.None);
  962. }
  963. public Task<int> UpdateAsync(DataTable dataTable, CancellationToken cancellationToken)
  964. {
  965. var result = new TaskCompletionSource<int>();
  966. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  967. {
  968. try
  969. {
  970. var update = base.Update(dataTable);
  971. result.SetResult(update);
  972. }
  973. catch (Exception ex)
  974. {
  975. result.SetException(ex);
  976. }
  977. }
  978. else
  979. {
  980. result.SetCanceled();
  981. }
  982. return result.Task;
  983. }
  984. /// <summary>
  985. /// Async version of Update
  986. /// </summary>
  987. /// <param name="dataRows">DataRow[] to use</param>
  988. /// <param name="tableMapping">Data Table Mapping</param>
  989. /// <returns>int</returns>
  990. public Task<int> UpdateAsync(DataRow[] dataRows, DataTableMapping tableMapping)
  991. {
  992. return UpdateAsync(dataRows, tableMapping, CancellationToken.None);
  993. }
  994. public Task<int> UpdateAsync(DataRow[] dataRows, DataTableMapping tableMapping, CancellationToken cancellationToken)
  995. {
  996. var result = new TaskCompletionSource<int>();
  997. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  998. {
  999. try
  1000. {
  1001. var update = base.Update(dataRows, tableMapping);
  1002. result.SetResult(update);
  1003. }
  1004. catch (Exception ex)
  1005. {
  1006. result.SetException(ex);
  1007. }
  1008. }
  1009. else
  1010. {
  1011. result.SetCanceled();
  1012. }
  1013. return result.Task;
  1014. }
  1015. /// <summary>
  1016. /// Async version of Update
  1017. /// </summary>
  1018. /// <param name="dataSet">DataSet to use</param>
  1019. /// <param name="srcTable">Source Table</param>
  1020. /// <returns></returns>
  1021. public Task<int> UpdateAsync(DataSet dataSet, string srcTable)
  1022. {
  1023. return UpdateAsync(dataSet, srcTable, CancellationToken.None);
  1024. }
  1025. public Task<int> UpdateAsync(DataSet dataSet, string srcTable, CancellationToken cancellationToken)
  1026. {
  1027. var result = new TaskCompletionSource<int>();
  1028. if (cancellationToken == CancellationToken.None || !cancellationToken.IsCancellationRequested)
  1029. {
  1030. try
  1031. {
  1032. var update = base.Update(dataSet, srcTable);
  1033. result.SetResult(update);
  1034. }
  1035. catch (Exception ex)
  1036. {
  1037. result.SetException(ex);
  1038. }
  1039. }
  1040. else
  1041. {
  1042. result.SetCanceled();
  1043. }
  1044. return result.Task;
  1045. }
  1046. #endregion
  1047. #endregion
  1048. }
  1049. /// <summary>
  1050. /// Represents the method that will handle the <see cref="MySqlDataAdapter.RowUpdating"/> event of a <see cref="MySqlDataAdapter"/>.
  1051. /// </summary>
  1052. internal delegate void MySqlRowUpdatingEventHandler(object sender, MySqlRowUpdatingEventArgs e);
  1053. /// <summary>
  1054. /// Represents the method that will handle the <see cref="MySqlDataAdapter.RowUpdated"/> event of a <see cref="MySqlDataAdapter"/>.
  1055. /// </summary>
  1056. internal delegate void MySqlRowUpdatedEventHandler(object sender, MySqlRowUpdatedEventArgs e);
  1057. /// <summary>
  1058. /// Provides data for the RowUpdating event. This class cannot be inherited.
  1059. /// </summary>
  1060. internal sealed class MySqlRowUpdatingEventArgs : RowUpdatingEventArgs
  1061. {
  1062. /// <summary>
  1063. /// Initializes a new instance of the MySqlRowUpdatingEventArgs class.
  1064. /// </summary>
  1065. /// <param name="row">The <see cref="DataRow"/> to
  1066. /// <see cref="DbDataAdapter.Update(DataSet)"/>.</param>
  1067. /// <param name="command">The <see cref="IDbCommand"/> to execute during <see cref="DbDataAdapter.Update(DataSet)"/>.</param>
  1068. /// <param name="statementType">One of the <see cref="StatementType"/> values that specifies the type of query executed.</param>
  1069. /// <param name="tableMapping">The <see cref="DataTableMapping"/> sent through an <see cref="DbDataAdapter.Update(DataSet)"/>.</param>
  1070. public MySqlRowUpdatingEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
  1071. : base(row, command, statementType, tableMapping)
  1072. {
  1073. }
  1074. /// <summary>
  1075. /// Gets or sets the MySqlCommand to execute when performing the Update.
  1076. /// </summary>
  1077. new public MySqlCommand Command
  1078. {
  1079. get { return (MySqlCommand)base.Command; }
  1080. set { base.Command = value; }
  1081. }
  1082. }
  1083. /// <summary>
  1084. /// Provides data for the RowUpdated event. This class cannot be inherited.
  1085. /// </summary>
  1086. internal sealed class MySqlRowUpdatedEventArgs : RowUpdatedEventArgs
  1087. {
  1088. /// <summary>
  1089. /// Initializes a new instance of the MySqlRowUpdatedEventArgs class.
  1090. /// </summary>
  1091. /// <param name="row">The <see cref="DataRow"/> sent through an <see cref="DbDataAdapter.Update(DataSet)"/>.</param>
  1092. /// <param name="command">The <see cref="IDbCommand"/> executed when <see cref="DbDataAdapter.Update(DataSet)"/> is called.</param>
  1093. /// <param name="statementType">One of the <see cref="StatementType"/> values that specifies the type of query executed.</param>
  1094. /// <param name="tableMapping">The <see cref="DataTableMapping"/> sent through an <see cref="DbDataAdapter.Update(DataSet)"/>.</param>
  1095. public MySqlRowUpdatedEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
  1096. : base(row, command, statementType, tableMapping)
  1097. {
  1098. }
  1099. /// <summary>
  1100. /// Gets or sets the MySqlCommand executed when Update is called.
  1101. /// </summary>
  1102. new public MySqlCommand Command
  1103. {
  1104. get { return (MySqlCommand)base.Command; }
  1105. }
  1106. }
  1107. }
  1108. #endif