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.

663 lines
26 KiB

4 years ago
  1. #if MYSQL_6_10
  2. // Copyright (c) 2004, 2019, 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.ComponentModel;
  25. using System.Reflection;
  26. using System.Text;
  27. using System.Collections;
  28. using System.Data;
  29. using Externals.MySql.Data.Types;
  30. using Externals.MySql.Data.Common;
  31. using System.Data.Common;
  32. using System.Globalization;
  33. namespace Externals.MySql.Data.MySqlClient
  34. {
  35. /// <summary>
  36. /// Represents a parameter to a <see cref="MySqlCommand"/>, This class cannot be inherited.
  37. /// </summary>
  38. [TypeConverter(typeof(MySqlParameterConverter))]
  39. internal sealed partial class MySqlParameter : DbParameter, IDbDataParameter
  40. {
  41. private const int UNSIGNED_MASK = 0x8000;
  42. private object _paramValue;
  43. private string _paramName;
  44. private MySqlDbType _mySqlDbType;
  45. private bool _inferType = true;
  46. private const int GEOMETRY_LENGTH = 25;
  47. private DbType _dbType;
  48. #region Constructors
  49. /// <summary>
  50. /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name, the <see cref="MySqlParameter.MySqlDbType"/>, the size, and the source column name.
  51. /// </summary>
  52. /// <param name="parameterName">The name of the parameter to map. </param>
  53. /// <param name="dbType">One of the <see cref="MySqlParameter.MySqlDbType"/> values. </param>
  54. /// <param name="size">The length of the parameter. </param>
  55. /// <param name="sourceColumn">The name of the source column. </param>
  56. public MySqlParameter(string parameterName, MySqlDbType dbType, int size, string sourceColumn) : this(parameterName, dbType)
  57. {
  58. Size = size;
  59. Direction = ParameterDirection.Input;
  60. SourceColumn = sourceColumn;
  61. SourceVersion = DataRowVersion.Default;
  62. }
  63. public MySqlParameter()
  64. {
  65. SourceVersion = DataRowVersion.Default;
  66. Direction = ParameterDirection.Input;
  67. }
  68. /// <summary>
  69. /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name and a value of the new MySqlParameter.
  70. /// </summary>
  71. /// <param name="parameterName">The name of the parameter to map. </param>
  72. /// <param name="value">An <see cref="Object"/> that is the value of the <see cref="MySqlParameter"/>. </param>
  73. public MySqlParameter(string parameterName, object value) : this()
  74. {
  75. ParameterName = parameterName;
  76. Value = value;
  77. }
  78. /// <summary>
  79. /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name and the data type.
  80. /// </summary>
  81. /// <param name="parameterName">The name of the parameter to map. </param>
  82. /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
  83. public MySqlParameter(string parameterName, MySqlDbType dbType) : this(parameterName, null)
  84. {
  85. MySqlDbType = dbType;
  86. }
  87. /// <summary>
  88. /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name, the <see cref="MySqlDbType"/>, and the size.
  89. /// </summary>
  90. /// <param name="parameterName">The name of the parameter to map. </param>
  91. /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
  92. /// <param name="size">The length of the parameter. </param>
  93. public MySqlParameter(string parameterName, MySqlDbType dbType, int size) : this(parameterName, dbType)
  94. {
  95. Size = size;
  96. }
  97. #if NETSTANDARD1_3
  98. /// <summary>
  99. /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name, the type of the parameter, the size of the parameter, a <see cref="ParameterDirection"/>, the precision of the parameter, the scale of the parameter, the source column, a <see cref="DataRowVersion"/> to use, and the value of the parameter.
  100. /// </summary>
  101. /// <param name="parameterName">The name of the parameter to map. </param>
  102. /// <param name="dbType">One of the <see cref="MySqlParameter.MySqlDbType"/> values. </param>
  103. /// <param name="size">The length of the parameter. </param>
  104. /// <param name="direction">One of the <see cref="ParameterDirection"/> values. </param>
  105. /// <param name="isNullable">true if the value of the field can be null, otherwise false. </param>
  106. /// <param name="precision">The total number of digits to the left and right of the decimal point to which <see cref="MySqlParameter.Value"/> is resolved.</param>
  107. /// <param name="scale">The total number of decimal places to which <see cref="MySqlParameter.Value"/> is resolved. </param>
  108. /// <param name="sourceColumn">The name of the source column. </param>
  109. /// <param name="value">An <see cref="Object"/> that is the value of the <see cref="MySqlParameter"/>. </param>
  110. /// <exception cref="ArgumentException"/>
  111. public MySqlParameter(string parameterName, MySqlDbType dbType, int size, ParameterDirection direction,
  112. bool isNullable, byte precision, byte scale, string sourceColumn, object value)
  113. : this(parameterName, dbType, size, sourceColumn)
  114. #else
  115. /// <summary>
  116. /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name, the type of the parameter, the size of the parameter, a <see cref="ParameterDirection"/>, the precision of the parameter, the scale of the parameter, the source column, a <see cref="DataRowVersion"/> to use, and the value of the parameter.
  117. /// </summary>
  118. /// <param name="parameterName">The name of the parameter to map. </param>
  119. /// <param name="dbType">One of the <see cref="MySqlParameter.MySqlDbType"/> values. </param>
  120. /// <param name="size">The length of the parameter. </param>
  121. /// <param name="direction">One of the <see cref="ParameterDirection"/> values. </param>
  122. /// <param name="isNullable">true if the value of the field can be null, otherwise false. </param>
  123. /// <param name="precision">The total number of digits to the left and right of the decimal point to which <see cref="MySqlParameter.Value"/> is resolved.</param>
  124. /// <param name="scale">The total number of decimal places to which <see cref="MySqlParameter.Value"/> is resolved. </param>
  125. /// <param name="sourceColumn">The name of the source column. </param>
  126. /// <param name="sourceVersion">One of the <see cref="DataRowVersion"/> values. </param>
  127. /// <param name="value">An <see cref="Object"/> that is the value of the <see cref="MySqlParameter"/>. </param>
  128. /// <exception cref="ArgumentException"/>
  129. public MySqlParameter(string parameterName, MySqlDbType dbType, int size, ParameterDirection direction,
  130. bool isNullable, byte precision, byte scale, string sourceColumn,
  131. DataRowVersion sourceVersion, object value)
  132. : this(parameterName, dbType, size, sourceColumn)
  133. #endif
  134. {
  135. Direction = direction;
  136. IsNullable = isNullable;
  137. Precision = precision;
  138. Scale = scale;
  139. Value = value;
  140. #if !NETSTANDARD1_3
  141. SourceVersion = sourceVersion;
  142. #endif
  143. }
  144. #if NETSTANDARD1_3
  145. internal MySqlParameter(string name, MySqlDbType type, ParameterDirection dir, string col, object val)
  146. : this(name, type)
  147. #else
  148. internal MySqlParameter(string name, MySqlDbType type, ParameterDirection dir, string col, DataRowVersion sourceVersion, object val)
  149. : this(name, type)
  150. #endif
  151. {
  152. Direction = dir;
  153. SourceColumn = col;
  154. Value = val;
  155. #if !NETSTANDARD1_3
  156. SourceVersion = sourceVersion;
  157. #endif
  158. }
  159. #endregion
  160. #region Properties
  161. [Category("Misc")]
  162. public override String ParameterName
  163. {
  164. get { return _paramName; }
  165. set { SetParameterName(value); }
  166. }
  167. internal MySqlParameterCollection Collection { get; set; }
  168. internal Encoding Encoding { get; set; }
  169. internal bool TypeHasBeenSet => _inferType == false;
  170. internal string BaseName
  171. {
  172. get
  173. {
  174. if (ParameterName.StartsWith("@", StringComparison.Ordinal) || ParameterName.StartsWith("?", StringComparison.Ordinal))
  175. return ParameterName.Substring(1);
  176. return ParameterName;
  177. }
  178. }
  179. /// <summary>
  180. /// Gets or sets a value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter.
  181. /// As of MySql version 4.1 and earlier, input-only is the only valid choice.
  182. /// </summary>
  183. [Category("Data")]
  184. public override ParameterDirection Direction { get; set; }
  185. /// <summary>
  186. /// Gets or sets a value indicating whether the parameter accepts null values.
  187. /// </summary>
  188. [Browsable(false)]
  189. public override Boolean IsNullable { get; set; }
  190. /// <summary>
  191. /// Gets or sets the <see cref="MySqlParameter.MySqlDbType"/> of the parameter.
  192. /// </summary>
  193. [Category("Data")]
  194. #if !NETSTANDARD1_3
  195. [DbProviderSpecificTypeProperty(true)]
  196. #endif
  197. public MySqlDbType MySqlDbType
  198. {
  199. get { return _mySqlDbType; }
  200. set
  201. {
  202. SetMySqlDbType(value);
  203. _inferType = false;
  204. }
  205. }
  206. /// <summary>
  207. /// Gets or sets the maximum number of digits used to represent the <see cref="Value"/> property.
  208. /// </summary>
  209. [Category("Data")]
  210. #if NET40
  211. public byte Precision { get; set; }
  212. #else
  213. public override byte Precision { get; set; }
  214. #endif
  215. /// <summary>
  216. /// Gets or sets the number of decimal places to which <see cref="Value"/> is resolved.
  217. /// </summary>
  218. [Category("Data")]
  219. #if NET40
  220. public byte Scale { get; set; }
  221. #else
  222. public override byte Scale { get; set; }
  223. #endif
  224. /// <summary>
  225. /// Gets or sets the maximum size, in bytes, of the data within the column.
  226. /// </summary>
  227. [Category("Data")]
  228. public override int Size { get; set; }
  229. /// <summary>
  230. /// Gets or sets the value of the parameter.
  231. /// </summary>
  232. [TypeConverter(typeof(StringConverter))]
  233. [Category("Data")]
  234. public override object Value
  235. {
  236. get { return _paramValue; }
  237. set
  238. {
  239. _paramValue = value;
  240. byte[] valueAsByte = value as byte[];
  241. string valueAsString = value as string;
  242. if (valueAsByte != null)
  243. Size = valueAsByte.Length;
  244. else if (valueAsString != null)
  245. Size = valueAsString.Length;
  246. if (_inferType)
  247. SetTypeFromValue();
  248. }
  249. }
  250. internal IMySqlValue ValueObject { get; private set; }
  251. /// <summary>
  252. /// Returns the possible values for this parameter if this parameter is of type
  253. /// SET or ENUM. Returns null otherwise.
  254. /// </summary>
  255. public IList PossibleValues { get; internal set; }
  256. /// <summary>
  257. /// Gets or sets the name of the source column that is mapped to the <see cref="System.Data.DataSet"/> and used for loading or returning the <see cref="MySqlParameter.Value"/>.
  258. /// </summary>
  259. [Category("Data")]
  260. public override String SourceColumn { get; set; }
  261. /// <summary>
  262. /// Sets or gets a value which indicates whether the source column is nullable.
  263. /// This allows <see cref="DbCommandBuilder"/> to correctly generate Update statements
  264. /// for nullable columns.
  265. /// </summary>
  266. public override bool SourceColumnNullMapping { get; set; }
  267. /// <summary>
  268. /// Gets or sets the <see cref="DbType"/> of the parameter.
  269. /// </summary>
  270. public override DbType DbType
  271. {
  272. get { return _dbType; }
  273. set
  274. {
  275. SetDbType(value);
  276. _inferType = false;
  277. }
  278. }
  279. #endregion
  280. private void SetParameterName(string name)
  281. {
  282. Collection?.ParameterNameChanged(this, _paramName, name);
  283. _paramName = name;
  284. }
  285. /// <summary>
  286. /// Overridden. Gets a string containing the <see cref="ParameterName"/>.
  287. /// </summary>
  288. /// <returns></returns>
  289. public override string ToString() => _paramName;
  290. internal int GetPSType()
  291. {
  292. switch (_mySqlDbType)
  293. {
  294. case MySqlDbType.Bit:
  295. return (int)MySqlDbType.Int64 | UNSIGNED_MASK;
  296. case MySqlDbType.UByte:
  297. return (int)MySqlDbType.Byte | UNSIGNED_MASK;
  298. case MySqlDbType.UInt64:
  299. return (int)MySqlDbType.Int64 | UNSIGNED_MASK;
  300. case MySqlDbType.UInt32:
  301. return (int)MySqlDbType.Int32 | UNSIGNED_MASK;
  302. case MySqlDbType.UInt24:
  303. return (int)MySqlDbType.Int32 | UNSIGNED_MASK;
  304. case MySqlDbType.UInt16:
  305. return (int)MySqlDbType.Int16 | UNSIGNED_MASK;
  306. case MySqlDbType.Guid:
  307. return (int)MySqlDbType.Guid - 600;
  308. default:
  309. int value = (int)_mySqlDbType;
  310. value = value > 255 ? value - 500 : value;
  311. return value;
  312. }
  313. }
  314. internal void Serialize(MySqlPacket packet, bool binary, MySqlConnectionStringBuilder settings)
  315. {
  316. if (!binary && (_paramValue == null || _paramValue == DBNull.Value))
  317. packet.WriteStringNoNull("NULL");
  318. else
  319. {
  320. if (ValueObject.MySqlDbType == MySqlDbType.Guid)
  321. {
  322. MySqlGuid g = (MySqlGuid)ValueObject;
  323. g.OldGuids = settings.OldGuids;
  324. ValueObject = g;
  325. }
  326. if (ValueObject.MySqlDbType == MySqlDbType.Geometry)
  327. {
  328. MySqlGeometry v = (MySqlGeometry)ValueObject;
  329. if (v.IsNull && Value != null)
  330. {
  331. MySqlGeometry.TryParse(Value.ToString(), out v);
  332. }
  333. ValueObject = v;
  334. }
  335. ValueObject.WriteValue(packet, binary, _paramValue, Size);
  336. }
  337. }
  338. private void SetMySqlDbType(MySqlDbType mysqlDbtype)
  339. {
  340. _mySqlDbType = mysqlDbtype;
  341. ValueObject = MySqlField.GetIMySqlValue(_mySqlDbType);
  342. SetDbTypeFromMySqlDbType();
  343. }
  344. private void SetTypeFromValue()
  345. {
  346. if (_paramValue == null || _paramValue == DBNull.Value) return;
  347. if (_paramValue is Guid)
  348. MySqlDbType = MySqlDbType.Guid;
  349. else if (_paramValue is TimeSpan)
  350. MySqlDbType = MySqlDbType.Time;
  351. else if (_paramValue is bool)
  352. MySqlDbType = MySqlDbType.Byte;
  353. else
  354. {
  355. Type t = _paramValue.GetType();
  356. switch (t.Name)
  357. {
  358. case "SByte": MySqlDbType = MySqlDbType.Byte; break;
  359. case "Byte": MySqlDbType = MySqlDbType.UByte; break;
  360. case "Int16": MySqlDbType = MySqlDbType.Int16; break;
  361. case "UInt16": MySqlDbType = MySqlDbType.UInt16; break;
  362. case "Int32": MySqlDbType = MySqlDbType.Int32; break;
  363. case "UInt32": MySqlDbType = MySqlDbType.UInt32; break;
  364. case "Int64": MySqlDbType = MySqlDbType.Int64; break;
  365. case "UInt64": MySqlDbType = MySqlDbType.UInt64; break;
  366. case "DateTime": MySqlDbType = MySqlDbType.DateTime; break;
  367. case "String": MySqlDbType = MySqlDbType.VarChar; break;
  368. case "Single": MySqlDbType = MySqlDbType.Float; break;
  369. case "Double": MySqlDbType = MySqlDbType.Double; break;
  370. case "Decimal": MySqlDbType = MySqlDbType.Decimal; break;
  371. case "Object":
  372. default:
  373. if (t.GetTypeInfo().BaseType == typeof(Enum))
  374. MySqlDbType = MySqlDbType.Int32;
  375. else
  376. MySqlDbType = MySqlDbType.Blob;
  377. break;
  378. }
  379. }
  380. }
  381. // this method is pretty dumb but we want it to be fast. it doesn't return size based
  382. // on value and type but just on the value.
  383. internal long EstimatedSize()
  384. {
  385. if (Value == null || Value == DBNull.Value)
  386. return 4; // size of NULL
  387. if (Value is byte[])
  388. return ((byte[])Value).Length;
  389. if (Value is string)
  390. return ((string)Value).Length * 4; // account for UTF-8 (yeah I know)
  391. if (Value is decimal || Value is float)
  392. return 64;
  393. return 32;
  394. }
  395. /// <summary>
  396. /// Resets the <b>DbType</b> property to its original settings.
  397. /// </summary>
  398. public override void ResetDbType()
  399. {
  400. _inferType = true;
  401. }
  402. void SetDbTypeFromMySqlDbType()
  403. {
  404. switch (_mySqlDbType)
  405. {
  406. case MySqlDbType.NewDecimal:
  407. case MySqlDbType.Decimal:
  408. _dbType = DbType.Decimal;
  409. break;
  410. case MySqlDbType.Byte:
  411. _dbType = DbType.SByte;
  412. break;
  413. case MySqlDbType.UByte:
  414. _dbType = DbType.Byte;
  415. break;
  416. case MySqlDbType.Int16:
  417. _dbType = DbType.Int16;
  418. break;
  419. case MySqlDbType.UInt16:
  420. _dbType = DbType.UInt16;
  421. break;
  422. case MySqlDbType.Int24:
  423. case MySqlDbType.Int32:
  424. _dbType = DbType.Int32;
  425. break;
  426. case MySqlDbType.UInt24:
  427. case MySqlDbType.UInt32:
  428. _dbType = DbType.UInt32;
  429. break;
  430. case MySqlDbType.Int64:
  431. _dbType = DbType.Int64;
  432. break;
  433. case MySqlDbType.UInt64:
  434. _dbType = DbType.UInt64;
  435. break;
  436. case MySqlDbType.Bit:
  437. _dbType = DbType.UInt64;
  438. break;
  439. case MySqlDbType.Float:
  440. _dbType = DbType.Single;
  441. break;
  442. case MySqlDbType.Double:
  443. _dbType = DbType.Double;
  444. break;
  445. case MySqlDbType.Timestamp:
  446. case MySqlDbType.DateTime:
  447. _dbType = DbType.DateTime;
  448. break;
  449. case MySqlDbType.Date:
  450. case MySqlDbType.Newdate:
  451. case MySqlDbType.Year:
  452. _dbType = DbType.Date;
  453. break;
  454. case MySqlDbType.Time:
  455. _dbType = DbType.Time;
  456. break;
  457. case MySqlDbType.Enum:
  458. case MySqlDbType.Set:
  459. case MySqlDbType.VarChar:
  460. _dbType = DbType.String;
  461. break;
  462. case MySqlDbType.TinyBlob:
  463. case MySqlDbType.MediumBlob:
  464. case MySqlDbType.LongBlob:
  465. case MySqlDbType.Blob:
  466. _dbType = DbType.Object;
  467. break;
  468. case MySqlDbType.String:
  469. _dbType = DbType.StringFixedLength;
  470. break;
  471. case MySqlDbType.Guid:
  472. _dbType = DbType.Guid;
  473. break;
  474. }
  475. }
  476. private void SetDbType(DbType dbType)
  477. {
  478. _dbType = dbType;
  479. switch (_dbType)
  480. {
  481. case DbType.Guid:
  482. _mySqlDbType = MySqlDbType.Guid;
  483. break;
  484. case DbType.AnsiString:
  485. case DbType.String:
  486. _mySqlDbType = MySqlDbType.VarChar;
  487. break;
  488. case DbType.AnsiStringFixedLength:
  489. case DbType.StringFixedLength:
  490. _mySqlDbType = MySqlDbType.String;
  491. break;
  492. case DbType.Boolean:
  493. case DbType.Byte:
  494. _mySqlDbType = MySqlDbType.UByte;
  495. break;
  496. case DbType.SByte:
  497. _mySqlDbType = MySqlDbType.Byte;
  498. break;
  499. case DbType.Date:
  500. _mySqlDbType = MySqlDbType.Date;
  501. break;
  502. case DbType.DateTime:
  503. _mySqlDbType = MySqlDbType.DateTime;
  504. break;
  505. case DbType.Time:
  506. _mySqlDbType = MySqlDbType.Time;
  507. break;
  508. case DbType.Single:
  509. _mySqlDbType = MySqlDbType.Float;
  510. break;
  511. case DbType.Double:
  512. _mySqlDbType = MySqlDbType.Double;
  513. break;
  514. case DbType.Int16:
  515. _mySqlDbType = MySqlDbType.Int16;
  516. break;
  517. case DbType.UInt16:
  518. _mySqlDbType = MySqlDbType.UInt16;
  519. break;
  520. case DbType.Int32:
  521. _mySqlDbType = MySqlDbType.Int32;
  522. break;
  523. case DbType.UInt32:
  524. _mySqlDbType = MySqlDbType.UInt32;
  525. break;
  526. case DbType.Int64:
  527. _mySqlDbType = MySqlDbType.Int64;
  528. break;
  529. case DbType.UInt64:
  530. _mySqlDbType = MySqlDbType.UInt64;
  531. break;
  532. case DbType.Decimal:
  533. case DbType.Currency:
  534. _mySqlDbType = MySqlDbType.Decimal;
  535. break;
  536. case DbType.Object:
  537. case DbType.VarNumeric:
  538. case DbType.Binary:
  539. default:
  540. _mySqlDbType = MySqlDbType.Blob;
  541. break;
  542. }
  543. if (_dbType == DbType.Object)
  544. {
  545. var value = this._paramValue as byte[];
  546. if (value != null && value.Length == GEOMETRY_LENGTH)
  547. _mySqlDbType = MySqlDbType.Geometry;
  548. }
  549. ValueObject = MySqlField.GetIMySqlValue(_mySqlDbType);
  550. }
  551. }
  552. internal class MySqlParameterConverter : TypeConverter
  553. {
  554. public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
  555. {
  556. #if !NETSTANDARD1_3
  557. if (destinationType == typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor))
  558. {
  559. return true;
  560. }
  561. #endif
  562. // Always call the base to see if it can perform the conversion.
  563. return base.CanConvertTo(context, destinationType);
  564. }
  565. public override object ConvertTo(ITypeDescriptorContext context,
  566. CultureInfo culture, object value, Type destinationType)
  567. {
  568. #if !NETSTANDARD1_3
  569. if (destinationType == typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor))
  570. {
  571. ConstructorInfo ci = typeof(MySqlParameter).GetConstructor(
  572. new[]
  573. {
  574. typeof (string), typeof (MySqlDbType), typeof (int), typeof (ParameterDirection),
  575. typeof (bool), typeof (byte), typeof (byte), typeof (string),
  576. typeof (object)
  577. });
  578. MySqlParameter p = (MySqlParameter)value;
  579. return new System.ComponentModel.Design.Serialization.InstanceDescriptor(ci, new object[]
  580. {
  581. p.ParameterName, p.DbType, p.Size, p.Direction,
  582. p.IsNullable, p.Precision,
  583. p.Scale, p.SourceColumn, p.Value
  584. });
  585. }
  586. #endif
  587. // Always call base, even if you can't convert.
  588. return base.ConvertTo(context, culture, value, destinationType);
  589. }
  590. }
  591. }
  592. #endif