SqlParameter.cs 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
  1. //
  2. // System.Data.SqlClient.SqlParameter.cs
  3. //
  4. // Author:
  5. // Rodrigo Moya ([email protected])
  6. // Daniel Morgan ([email protected])
  7. // Tim Coleman ([email protected])
  8. // Diego Caravana ([email protected])
  9. // Umadevi S ([email protected])
  10. // Amit Biswas ([email protected])
  11. // Veerapuram Varadhan ([email protected])
  12. //
  13. // (C) Ximian, Inc. 2002
  14. // Copyright (C) Tim Coleman, 2002
  15. //
  16. //
  17. // Copyright (C) 2004, 2008, 2009 Novell, Inc (http://www.novell.com)
  18. //
  19. // Permission is hereby granted, free of charge, to any person obtaining
  20. // a copy of this software and associated documentation files (the
  21. // "Software"), to deal in the Software without restriction, including
  22. // without limitation the rights to use, copy, modify, merge, publish,
  23. // distribute, sublicense, and/or sell copies of the Software, and to
  24. // permit persons to whom the Software is furnished to do so, subject to
  25. // the following conditions:
  26. //
  27. // The above copyright notice and this permission notice shall be
  28. // included in all copies or substantial portions of the Software.
  29. //
  30. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  31. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  32. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  33. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  34. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  35. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  36. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  37. //
  38. using Mono.Data.Tds;
  39. using Mono.Data.Tds.Protocol;
  40. using System;
  41. using System.Collections;
  42. using System.ComponentModel;
  43. using System.Data;
  44. using System.Data.Common;
  45. using System.Data.SqlTypes;
  46. using System.Globalization;
  47. using System.Runtime.InteropServices;
  48. using System.Text;
  49. using System.Xml;
  50. namespace System.Data.SqlClient {
  51. #if NET_2_0
  52. [TypeConverterAttribute ("System.Data.SqlClient.SqlParameter+SqlParameterConverter, " + Consts.AssemblySystem_Data)]
  53. public sealed class SqlParameter : DbParameter, IDbDataParameter, IDataParameter, ICloneable
  54. #else
  55. [TypeConverterAttribute (typeof (SqlParameterConverter))]
  56. public sealed class SqlParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
  57. #endif // NET_2_0
  58. {
  59. #region Fields
  60. TdsMetaParameter metaParameter;
  61. SqlParameterCollection container;
  62. DbType dbType;
  63. ParameterDirection direction = ParameterDirection.Input;
  64. bool isTypeSet;
  65. int offset;
  66. SqlDbType sqlDbType;
  67. string sourceColumn;
  68. DataRowVersion sourceVersion;
  69. SqlCompareOptions compareInfo;
  70. int localeId;
  71. Type sqlType;
  72. bool typeChanged;
  73. #if NET_2_0
  74. bool sourceColumnNullMapping;
  75. string xmlSchemaCollectionDatabase = String.Empty;
  76. string xmlSchemaCollectionOwningSchema = String.Empty;
  77. string xmlSchemaCollectionName = String.Empty;
  78. #else
  79. static Hashtable DbTypeMapping;
  80. #endif
  81. static Hashtable type_mapping;
  82. #endregion // Fields
  83. #region Constructors
  84. static SqlParameter ()
  85. {
  86. if (DbTypeMapping == null)
  87. DbTypeMapping = new Hashtable ();
  88. DbTypeMapping.Add (SqlDbType.BigInt, typeof (long));
  89. DbTypeMapping.Add (SqlDbType.Bit, typeof (bool));
  90. DbTypeMapping.Add (SqlDbType.Char, typeof (string));
  91. DbTypeMapping.Add (SqlDbType.NChar, typeof (string));
  92. DbTypeMapping.Add (SqlDbType.Text, typeof (string));
  93. DbTypeMapping.Add (SqlDbType.NText, typeof (string));
  94. DbTypeMapping.Add (SqlDbType.VarChar, typeof (string));
  95. DbTypeMapping.Add (SqlDbType.NVarChar, typeof (string));
  96. DbTypeMapping.Add (SqlDbType.SmallDateTime, typeof (DateTime));
  97. DbTypeMapping.Add (SqlDbType.DateTime, typeof (DateTime));
  98. DbTypeMapping.Add (SqlDbType.Decimal, typeof (decimal));
  99. DbTypeMapping.Add (SqlDbType.Float, typeof (double));
  100. DbTypeMapping.Add (SqlDbType.Binary, typeof (byte []));
  101. DbTypeMapping.Add (SqlDbType.Image, typeof (byte []));
  102. DbTypeMapping.Add (SqlDbType.Money, typeof (decimal));
  103. DbTypeMapping.Add (SqlDbType.SmallMoney, typeof (decimal));
  104. DbTypeMapping.Add (SqlDbType.VarBinary, typeof (byte []));
  105. DbTypeMapping.Add (SqlDbType.TinyInt, typeof (byte));
  106. DbTypeMapping.Add (SqlDbType.Int, typeof (int));
  107. DbTypeMapping.Add (SqlDbType.Real, typeof (float));
  108. DbTypeMapping.Add (SqlDbType.SmallInt, typeof (short));
  109. DbTypeMapping.Add (SqlDbType.UniqueIdentifier, typeof (Guid));
  110. DbTypeMapping.Add (SqlDbType.Variant, typeof (object));
  111. #if NET_2_0
  112. DbTypeMapping.Add (SqlDbType.Xml, typeof (string));
  113. #endif
  114. type_mapping = new Hashtable ();
  115. type_mapping.Add (typeof (long), SqlDbType.BigInt);
  116. type_mapping.Add (typeof (SqlTypes.SqlInt64), SqlDbType.BigInt);
  117. type_mapping.Add (typeof (bool), SqlDbType.Bit);
  118. type_mapping.Add (typeof (SqlTypes.SqlBoolean), SqlDbType.Bit);
  119. #if NET_2_0
  120. type_mapping.Add (typeof (char), SqlDbType.NVarChar);
  121. type_mapping.Add (typeof (char []), SqlDbType.NVarChar);
  122. type_mapping.Add (typeof (SqlTypes.SqlChars), SqlDbType.NVarChar);
  123. #endif
  124. type_mapping.Add (typeof (string), SqlDbType.NVarChar);
  125. type_mapping.Add (typeof (SqlTypes.SqlString), SqlDbType.NVarChar);
  126. type_mapping.Add (typeof (DateTime), SqlDbType.DateTime);
  127. type_mapping.Add (typeof (SqlTypes.SqlDateTime), SqlDbType.DateTime);
  128. type_mapping.Add (typeof (decimal), SqlDbType.Decimal);
  129. type_mapping.Add (typeof (SqlTypes.SqlDecimal), SqlDbType.Decimal);
  130. type_mapping.Add (typeof (double), SqlDbType.Float);
  131. type_mapping.Add (typeof (SqlTypes.SqlDouble), SqlDbType.Float);
  132. type_mapping.Add (typeof (byte []), SqlDbType.VarBinary);
  133. type_mapping.Add (typeof (SqlTypes.SqlBinary), SqlDbType.VarBinary);
  134. #if NET_2_0
  135. type_mapping.Add (typeof (SqlTypes.SqlBytes), SqlDbType.VarBinary);
  136. #endif
  137. type_mapping.Add (typeof (byte), SqlDbType.TinyInt);
  138. type_mapping.Add (typeof (SqlTypes.SqlByte), SqlDbType.TinyInt);
  139. type_mapping.Add (typeof (int), SqlDbType.Int);
  140. type_mapping.Add (typeof (SqlTypes.SqlInt32), SqlDbType.Int);
  141. type_mapping.Add (typeof (float), SqlDbType.Real);
  142. type_mapping.Add (typeof (SqlTypes.SqlSingle), SqlDbType.Real);
  143. type_mapping.Add (typeof (short), SqlDbType.SmallInt);
  144. type_mapping.Add (typeof (SqlTypes.SqlInt16), SqlDbType.SmallInt);
  145. type_mapping.Add (typeof (Guid), SqlDbType.UniqueIdentifier);
  146. type_mapping.Add (typeof (SqlTypes.SqlGuid), SqlDbType.UniqueIdentifier);
  147. type_mapping.Add (typeof (SqlTypes.SqlMoney), SqlDbType.Money);
  148. #if NET_2_0
  149. type_mapping.Add (typeof (XmlReader), SqlDbType.Xml);
  150. type_mapping.Add (typeof (SqlTypes.SqlXml), SqlDbType.Xml);
  151. #endif
  152. type_mapping.Add (typeof (object), SqlDbType.Variant);
  153. }
  154. public SqlParameter ()
  155. : this (String.Empty, SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
  156. {
  157. isTypeSet = false;
  158. }
  159. public SqlParameter (string parameterName, object value)
  160. {
  161. if (parameterName == null)
  162. parameterName = string.Empty;
  163. metaParameter = new TdsMetaParameter (parameterName, GetFrameworkValue);
  164. metaParameter.RawValue = value;
  165. InferSqlType (value);
  166. sourceVersion = DataRowVersion.Current;
  167. }
  168. public SqlParameter (string parameterName, SqlDbType dbType)
  169. : this (parameterName, dbType, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, null)
  170. {
  171. }
  172. public SqlParameter (string parameterName, SqlDbType dbType, int size)
  173. : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, null)
  174. {
  175. }
  176. public SqlParameter (string parameterName, SqlDbType dbType, int size, string sourceColumn)
  177. : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, sourceColumn, DataRowVersion.Current, null)
  178. {
  179. }
  180. [EditorBrowsable (EditorBrowsableState.Advanced)]
  181. public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
  182. {
  183. if (parameterName == null)
  184. parameterName = string.Empty;
  185. metaParameter = new TdsMetaParameter (parameterName, size,
  186. isNullable, precision,
  187. scale,
  188. GetFrameworkValue);
  189. metaParameter.RawValue = value;
  190. if (dbType != SqlDbType.Variant)
  191. SqlDbType = dbType;
  192. Direction = direction;
  193. SourceColumn = sourceColumn;
  194. SourceVersion = sourceVersion;
  195. }
  196. #if NET_2_0
  197. public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, bool sourceColumnNullMapping, Object value, string xmlSchemaCollectionDatabase, string xmlSchemaCollectionOwningSchema, string xmlSchemaCollectionName)
  198. : this (parameterName, dbType, size, direction, false, precision, scale, sourceColumn, sourceVersion, value)
  199. {
  200. XmlSchemaCollectionDatabase = xmlSchemaCollectionDatabase;
  201. XmlSchemaCollectionOwningSchema = xmlSchemaCollectionOwningSchema;
  202. XmlSchemaCollectionName = xmlSchemaCollectionName;
  203. SourceColumnNullMapping = sourceColumnNullMapping;
  204. }
  205. #endif
  206. // This constructor is used internally to construct a
  207. // SqlParameter. The value array comes from sp_procedure_params_rowset.
  208. // This is in SqlCommand.DeriveParameters.
  209. //
  210. // http://social.msdn.microsoft.com/forums/en-US/transactsql/thread/900756fd-3980-48e3-ae59-a15d7fc15b4c/
  211. internal SqlParameter (object[] dbValues)
  212. : this (dbValues [3].ToString (), (object) null)
  213. {
  214. ParameterName = (string) dbValues [3];
  215. switch ((short) dbValues [5]) {
  216. case 1:
  217. Direction = ParameterDirection.Input;
  218. break;
  219. case 2:
  220. Direction = ParameterDirection.InputOutput;
  221. break;
  222. case 3:
  223. Direction = ParameterDirection.Output;
  224. break;
  225. case 4:
  226. Direction = ParameterDirection.ReturnValue;
  227. break;
  228. default:
  229. Direction = ParameterDirection.Input;
  230. break;
  231. }
  232. SqlDbType = (SqlDbType) FrameworkDbTypeFromName ((string) dbValues [16]);
  233. if (MetaParameter.IsVariableSizeType) {
  234. if (dbValues [10] != DBNull.Value)
  235. Size = (int) dbValues [10];
  236. }
  237. if (SqlDbType == SqlDbType.Decimal) {
  238. if (dbValues [12] != null && dbValues [12] != DBNull.Value)
  239. Precision = (byte) ((short) dbValues [12]);
  240. if (dbValues [13] != null && dbValues [13] != DBNull.Value)
  241. Scale = (byte) ((short) dbValues [13]);
  242. }
  243. }
  244. #endregion // Constructors
  245. #region Properties
  246. // Used to ensure that only one collection can contain this
  247. // parameter
  248. internal SqlParameterCollection Container {
  249. get { return container; }
  250. set { container = value; }
  251. }
  252. internal void CheckIfInitialized ()
  253. {
  254. if (!isTypeSet)
  255. throw new Exception ("all parameters to have an explicity set type");
  256. if (MetaParameter.IsVariableSizeType) {
  257. if (SqlDbType == SqlDbType.Decimal && Precision == 0)
  258. throw new Exception ("Parameter of type 'Decimal' have an explicitly set Precision and Scale");
  259. else if (Size == 0)
  260. throw new Exception ("all variable length parameters to have an explicitly set non-zero Size");
  261. }
  262. }
  263. #if ONLY_1_0 || ONLY_1_1
  264. [Browsable (false)]
  265. [DataSysDescription ("The parameter generic type.")]
  266. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  267. [RefreshProperties (RefreshProperties.All)]
  268. [DataCategory ("Data")]
  269. #endif
  270. public
  271. #if NET_2_0
  272. override
  273. #endif // NET_2_0
  274. DbType DbType {
  275. get { return dbType; }
  276. set {
  277. SetDbType (value);
  278. typeChanged = true;
  279. isTypeSet = true;
  280. }
  281. }
  282. #if ONLY_1_0 || ONLY_1_1
  283. [DataCategory ("Data")]
  284. [DataSysDescription ("Input, output, or bidirectional parameter.")]
  285. [DefaultValue (ParameterDirection.Input)]
  286. #endif
  287. #if NET_2_0
  288. [RefreshProperties (RefreshProperties.All)]
  289. #endif
  290. public
  291. #if NET_2_0
  292. override
  293. #endif // NET_2_0
  294. ParameterDirection Direction {
  295. get { return direction; }
  296. set {
  297. direction = value;
  298. switch( direction ) {
  299. case ParameterDirection.Output:
  300. MetaParameter.Direction = TdsParameterDirection.Output;
  301. break;
  302. case ParameterDirection.InputOutput:
  303. MetaParameter.Direction = TdsParameterDirection.InputOutput;
  304. break;
  305. case ParameterDirection.ReturnValue:
  306. MetaParameter.Direction = TdsParameterDirection.ReturnValue;
  307. break;
  308. }
  309. }
  310. }
  311. internal TdsMetaParameter MetaParameter {
  312. get { return metaParameter; }
  313. }
  314. #if ONLY_1_0 || ONLY_1_1
  315. [Browsable (false)]
  316. [DataSysDescription ("a design-time property used for strongly typed code-generation.")]
  317. [DefaultValue (false)]
  318. [DesignOnly (true)]
  319. [EditorBrowsable (EditorBrowsableState.Advanced)]
  320. #endif
  321. public
  322. #if NET_2_0
  323. override
  324. #endif // NET_2_0
  325. bool IsNullable {
  326. get { return metaParameter.IsNullable; }
  327. set { metaParameter.IsNullable = value; }
  328. }
  329. [Browsable (false)]
  330. #if ONLY_1_0 || ONLY_1_1
  331. [DataCategory ("Data")]
  332. [DataSysDescription ("Offset in variable length data types.")]
  333. [DefaultValue (0)]
  334. #endif
  335. #if NET_2_0
  336. [EditorBrowsable (EditorBrowsableState.Advanced)]
  337. #endif
  338. public int Offset {
  339. get { return offset; }
  340. set { offset = value; }
  341. }
  342. #if ONLY_1_0 || ONLY_1_1
  343. [DataSysDescription ("Name of the parameter, like '@p1'")]
  344. [DefaultValue ("")]
  345. #endif
  346. public
  347. #if NET_2_0
  348. override
  349. #endif // NET_2_0
  350. string ParameterName {
  351. get { return metaParameter.ParameterName; }
  352. set {
  353. if (value == null)
  354. value = string.Empty;
  355. metaParameter.ParameterName = value;
  356. }
  357. }
  358. [DefaultValue (0)]
  359. #if ONLY_1_0 || ONLY_1_1
  360. [DataCategory ("Data")]
  361. [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
  362. #endif
  363. public byte Precision {
  364. get { return metaParameter.Precision; }
  365. set { metaParameter.Precision = value; }
  366. }
  367. [DefaultValue (0)]
  368. #if ONLY_1_0 || ONLY_1_1
  369. [DataCategory ("Data")]
  370. [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
  371. #endif
  372. public byte Scale {
  373. get { return metaParameter.Scale; }
  374. set { metaParameter.Scale = value; }
  375. }
  376. #if ONLY_1_0 || ONLY_1_1
  377. [DataCategory ("Data")]
  378. [DataSysDescription ("Size of variable length data types (string & arrays).")]
  379. [DefaultValue (0)]
  380. #endif
  381. public
  382. #if NET_2_0
  383. override
  384. #endif // NET_2_0
  385. int Size {
  386. get { return metaParameter.Size; }
  387. set { metaParameter.Size = value; }
  388. }
  389. #if ONLY_1_0 || ONLY_1_1
  390. [DataCategory ("Data")]
  391. [DataSysDescription ("When used by a DataAdapter.Update, the source column name that is used to find the DataSetColumn name in the ColumnMappings. This is to copy a value between the parameter and a datarow.")]
  392. [DefaultValue ("")]
  393. #endif
  394. public
  395. #if NET_2_0
  396. override
  397. #endif // NET_2_0
  398. string SourceColumn {
  399. get {
  400. if (sourceColumn == null)
  401. return string.Empty;
  402. return sourceColumn;
  403. }
  404. set { sourceColumn = value; }
  405. }
  406. #if ONLY_1_0 || ONLY_1_1
  407. [DataCategory ("Data")]
  408. [DataSysDescription ("When used by a DataAdapter.Update (UpdateCommand only), the version of the DataRow value that is used to update the data source.")]
  409. [DefaultValue (DataRowVersion.Current)]
  410. #endif
  411. public
  412. #if NET_2_0
  413. override
  414. #endif // NET_2_0
  415. DataRowVersion SourceVersion {
  416. get { return sourceVersion; }
  417. set { sourceVersion = value; }
  418. }
  419. #if ONLY_1_0 || ONLY_1_1
  420. [DataCategory ("Data")]
  421. [DataSysDescription ("The parameter native type.")]
  422. [DefaultValue (SqlDbType.NVarChar)]
  423. #endif
  424. [RefreshProperties (RefreshProperties.All)]
  425. #if NET_2_0
  426. [DbProviderSpecificTypeProperty(true)]
  427. #endif
  428. public SqlDbType SqlDbType {
  429. get { return sqlDbType; }
  430. set {
  431. SetSqlDbType (value);
  432. typeChanged = true;
  433. isTypeSet = true;
  434. }
  435. }
  436. [TypeConverterAttribute (typeof (StringConverter))]
  437. #if ONLY_1_0 || ONLY_1_1
  438. [DataCategory ("Data")]
  439. [DataSysDescription ("Value of the parameter.")]
  440. [DefaultValue (null)]
  441. #else
  442. [RefreshProperties (RefreshProperties.All)]
  443. #endif
  444. public
  445. #if NET_2_0
  446. override
  447. #endif // NET_2_0
  448. object Value {
  449. get {
  450. if (sqlType != null)
  451. return GetSqlValue (metaParameter.RawValue);
  452. return metaParameter.RawValue;
  453. }
  454. set {
  455. if (!isTypeSet) {
  456. #if NET_2_0
  457. InferSqlType (value);
  458. #else
  459. if (value != null && value != DBNull.Value)
  460. InferSqlType (value);
  461. #endif
  462. }
  463. if (value is INullable) {
  464. sqlType = value.GetType ();
  465. value = SqlTypeToFrameworkType (value);
  466. }
  467. metaParameter.RawValue = value;
  468. }
  469. }
  470. #if NET_2_0
  471. [Browsable (false)]
  472. public SqlCompareOptions CompareInfo{
  473. get{ return compareInfo; }
  474. set{ compareInfo = value; }
  475. }
  476. [Browsable (false)]
  477. public int LocaleId {
  478. get { return localeId; }
  479. set { localeId = value; }
  480. }
  481. [Browsable (false)]
  482. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  483. public Object SqlValue {
  484. get {
  485. return GetSqlValue (metaParameter.RawValue);
  486. }
  487. set {
  488. Value = value;
  489. }
  490. }
  491. public override bool SourceColumnNullMapping {
  492. get { return sourceColumnNullMapping; }
  493. set { sourceColumnNullMapping = value; }
  494. }
  495. public string XmlSchemaCollectionDatabase {
  496. get { return xmlSchemaCollectionDatabase; }
  497. set { xmlSchemaCollectionDatabase = (value == null ? String.Empty : value); }
  498. }
  499. public string XmlSchemaCollectionName {
  500. get { return xmlSchemaCollectionName; }
  501. set {
  502. xmlSchemaCollectionName = (value == null ? String.Empty : value);
  503. }
  504. }
  505. public string XmlSchemaCollectionOwningSchema {
  506. get { return xmlSchemaCollectionOwningSchema; }
  507. set {
  508. xmlSchemaCollectionOwningSchema = (value == null ? String.Empty : value);
  509. }
  510. }
  511. #endif
  512. #endregion // Properties
  513. #region Methods
  514. object ICloneable.Clone ()
  515. {
  516. return new SqlParameter (ParameterName, SqlDbType, Size, Direction, IsNullable, Precision, Scale, SourceColumn, SourceVersion, Value);
  517. }
  518. // If the value is set without the DbType/SqlDbType being set, then we
  519. // infer type information.
  520. void InferSqlType (object value)
  521. {
  522. if (value == null || value == DBNull.Value) {
  523. SetSqlDbType (SqlDbType.NVarChar);
  524. return;
  525. }
  526. Type type = value.GetType ();
  527. if (type.IsEnum)
  528. type = Enum.GetUnderlyingType (type);
  529. object t = type_mapping [type];
  530. if (t == null)
  531. throw new ArgumentException (String.Format ("The parameter data type of {0} is invalid.", type.FullName));
  532. SetSqlDbType ((SqlDbType) t);
  533. }
  534. // Returns System.Type corresponding to the underlying SqlDbType
  535. #if NET_2_0
  536. internal override
  537. #endif
  538. Type SystemType {
  539. get {
  540. return (Type) DbTypeMapping [sqlDbType];
  541. }
  542. }
  543. #if NET_2_0
  544. internal override object FrameworkDbType {
  545. get {
  546. return sqlDbType;
  547. }
  548. set {
  549. object t;
  550. try {
  551. t = (DbType) DbTypeFromName ((string)value);
  552. SetDbType ((DbType)t);
  553. } catch (ArgumentException) {
  554. t = (SqlDbType)FrameworkDbTypeFromName ((string)value);
  555. SetSqlDbType ((SqlDbType) t);
  556. }
  557. }
  558. }
  559. DbType DbTypeFromName (string name)
  560. {
  561. switch (name.ToLower ()) {
  562. case "ansistring":
  563. return DbType.AnsiString;
  564. case "ansistringfixedlength":
  565. return DbType.AnsiStringFixedLength;
  566. case "binary":
  567. return DbType.Binary;
  568. case "boolean":
  569. return DbType.Boolean;
  570. case "byte":
  571. return DbType.Byte;
  572. case "currency":
  573. return DbType.Currency;
  574. case "date":
  575. return DbType.Date;
  576. case "datetime":
  577. return DbType.DateTime;
  578. case "decimal":
  579. return DbType.Decimal;
  580. case "double":
  581. return DbType.Double;
  582. case "guid":
  583. return DbType.Guid;
  584. case "int16":
  585. return DbType.Int16;
  586. case "int32":
  587. return DbType.Int32;
  588. case "int64":
  589. return DbType.Int64;
  590. case "object":
  591. return DbType.Object;
  592. case "single":
  593. return DbType.Single;
  594. case "string":
  595. return DbType.String;
  596. case "stringfixedlength":
  597. return DbType.StringFixedLength;
  598. case "time":
  599. return DbType.Time;
  600. case "xml":
  601. return DbType.Xml;
  602. default:
  603. string exception = String.Format ("No mapping exists from {0} to a known DbType.", name);
  604. throw new ArgumentException (exception);
  605. }
  606. }
  607. #endif
  608. // When the DbType is set, we also set the SqlDbType, as well as the SQL Server
  609. // string representation of the type name. If the DbType is not convertible
  610. // to an SqlDbType, throw an exception.
  611. private void SetDbType (DbType type)
  612. {
  613. switch (type) {
  614. case DbType.AnsiString:
  615. MetaParameter.TypeName = "varchar";
  616. sqlDbType = SqlDbType.VarChar;
  617. MetaParameter.IsVariableSizeType = true;
  618. break;
  619. case DbType.AnsiStringFixedLength:
  620. MetaParameter.TypeName = "char";
  621. sqlDbType = SqlDbType.Char;
  622. MetaParameter.IsVariableSizeType = true;
  623. break;
  624. case DbType.Binary:
  625. MetaParameter.TypeName = "varbinary";
  626. sqlDbType = SqlDbType.VarBinary;
  627. MetaParameter.IsVariableSizeType = true;
  628. break;
  629. case DbType.Boolean:
  630. MetaParameter.TypeName = "bit";
  631. sqlDbType = SqlDbType.Bit;
  632. break;
  633. case DbType.Byte:
  634. MetaParameter.TypeName = "tinyint";
  635. sqlDbType = SqlDbType.TinyInt;
  636. break;
  637. case DbType.Currency:
  638. sqlDbType = SqlDbType.Money;
  639. MetaParameter.TypeName = "money";
  640. break;
  641. case DbType.Date:
  642. case DbType.DateTime:
  643. MetaParameter.TypeName = "datetime";
  644. sqlDbType = SqlDbType.DateTime;
  645. break;
  646. case DbType.Decimal:
  647. MetaParameter.TypeName = "decimal";
  648. sqlDbType = SqlDbType.Decimal;
  649. break;
  650. case DbType.Double:
  651. MetaParameter.TypeName = "float";
  652. sqlDbType = SqlDbType.Float;
  653. break;
  654. case DbType.Guid:
  655. MetaParameter.TypeName = "uniqueidentifier";
  656. sqlDbType = SqlDbType.UniqueIdentifier;
  657. break;
  658. case DbType.Int16:
  659. MetaParameter.TypeName = "smallint";
  660. sqlDbType = SqlDbType.SmallInt;
  661. break;
  662. case DbType.Int32:
  663. MetaParameter.TypeName = "int";
  664. sqlDbType = SqlDbType.Int;
  665. break;
  666. case DbType.Int64:
  667. MetaParameter.TypeName = "bigint";
  668. sqlDbType = SqlDbType.BigInt;
  669. break;
  670. case DbType.Object:
  671. MetaParameter.TypeName = "sql_variant";
  672. sqlDbType = SqlDbType.Variant;
  673. break;
  674. case DbType.Single:
  675. MetaParameter.TypeName = "real";
  676. sqlDbType = SqlDbType.Real;
  677. break;
  678. case DbType.String:
  679. MetaParameter.TypeName = "nvarchar";
  680. sqlDbType = SqlDbType.NVarChar;
  681. MetaParameter.IsVariableSizeType = true;
  682. break;
  683. case DbType.StringFixedLength:
  684. MetaParameter.TypeName = "nchar";
  685. sqlDbType = SqlDbType.NChar;
  686. MetaParameter.IsVariableSizeType = true;
  687. break;
  688. case DbType.Time:
  689. MetaParameter.TypeName = "datetime";
  690. sqlDbType = SqlDbType.DateTime;
  691. break;
  692. #if NET_2_0
  693. // Handle Xml type as string
  694. case DbType.Xml:
  695. MetaParameter.TypeName = "xml";
  696. sqlDbType = SqlDbType.Xml;
  697. MetaParameter.IsVariableSizeType = true;
  698. break;
  699. #endif
  700. default:
  701. string exception = String.Format ("No mapping exists from DbType {0} to a known SqlDbType.", type);
  702. throw new ArgumentException (exception);
  703. }
  704. dbType = type;
  705. }
  706. // Used by internal constructor which has a SQL Server typename
  707. private SqlDbType FrameworkDbTypeFromName (string dbTypeName)
  708. {
  709. switch (dbTypeName.ToLower ()) {
  710. case "bigint":
  711. return SqlDbType.BigInt;
  712. case "binary":
  713. return SqlDbType.Binary;
  714. case "bit":
  715. return SqlDbType.Bit;
  716. case "char":
  717. return SqlDbType.Char;
  718. case "datetime":
  719. return SqlDbType.DateTime;
  720. case "decimal":
  721. return SqlDbType.Decimal;
  722. case "float":
  723. return SqlDbType.Float;
  724. case "image":
  725. return SqlDbType.Image;
  726. case "int":
  727. return SqlDbType.Int;
  728. case "money":
  729. return SqlDbType.Money;
  730. case "nchar":
  731. return SqlDbType.NChar;
  732. case "ntext":
  733. return SqlDbType.NText;
  734. case "nvarchar":
  735. return SqlDbType.NVarChar;
  736. case "real":
  737. return SqlDbType.Real;
  738. case "smalldatetime":
  739. return SqlDbType.SmallDateTime;
  740. case "smallint":
  741. return SqlDbType.SmallInt;
  742. case "smallmoney":
  743. return SqlDbType.SmallMoney;
  744. case "text":
  745. return SqlDbType.Text;
  746. case "timestamp":
  747. return SqlDbType.Timestamp;
  748. case "tinyint":
  749. return SqlDbType.TinyInt;
  750. case "uniqueidentifier":
  751. return SqlDbType.UniqueIdentifier;
  752. case "varbinary":
  753. return SqlDbType.VarBinary;
  754. case "varchar":
  755. return SqlDbType.VarChar;
  756. case "sql_variant":
  757. return SqlDbType.Variant;
  758. #if NET_2_0
  759. case "xml":
  760. return SqlDbType.Xml;
  761. #endif
  762. default:
  763. return SqlDbType.Variant;
  764. }
  765. }
  766. // When the SqlDbType is set, we also set the DbType, as well as the SQL Server
  767. // string representation of the type name. If the SqlDbType is not convertible
  768. // to a DbType, throw an exception.
  769. internal void SetSqlDbType (SqlDbType type)
  770. {
  771. switch (type) {
  772. case SqlDbType.BigInt:
  773. MetaParameter.TypeName = "bigint";
  774. dbType = DbType.Int64;
  775. break;
  776. case SqlDbType.Binary:
  777. MetaParameter.TypeName = "binary";
  778. dbType = DbType.Binary;
  779. MetaParameter.IsVariableSizeType = true;
  780. break;
  781. case SqlDbType.Timestamp:
  782. MetaParameter.TypeName = "timestamp";
  783. dbType = DbType.Binary;
  784. break;
  785. case SqlDbType.VarBinary:
  786. MetaParameter.TypeName = "varbinary";
  787. dbType = DbType.Binary;
  788. MetaParameter.IsVariableSizeType = true;
  789. break;
  790. case SqlDbType.Bit:
  791. MetaParameter.TypeName = "bit";
  792. dbType = DbType.Boolean;
  793. break;
  794. case SqlDbType.Char:
  795. MetaParameter.TypeName = "char";
  796. dbType = DbType.AnsiStringFixedLength;
  797. MetaParameter.IsVariableSizeType = true;
  798. break;
  799. case SqlDbType.DateTime:
  800. MetaParameter.TypeName = "datetime";
  801. dbType = DbType.DateTime;
  802. break;
  803. case SqlDbType.SmallDateTime:
  804. MetaParameter.TypeName = "smalldatetime";
  805. dbType = DbType.DateTime;
  806. break;
  807. case SqlDbType.Decimal:
  808. MetaParameter.TypeName = "decimal";
  809. dbType = DbType.Decimal;
  810. break;
  811. case SqlDbType.Float:
  812. MetaParameter.TypeName = "float";
  813. dbType = DbType.Double;
  814. break;
  815. case SqlDbType.Image:
  816. MetaParameter.TypeName = "image";
  817. dbType = DbType.Binary;
  818. MetaParameter.IsVariableSizeType = true;
  819. break;
  820. case SqlDbType.Int:
  821. MetaParameter.TypeName = "int";
  822. dbType = DbType.Int32;
  823. break;
  824. case SqlDbType.Money:
  825. MetaParameter.TypeName = "money";
  826. dbType = DbType.Currency;
  827. break;
  828. case SqlDbType.SmallMoney:
  829. MetaParameter.TypeName = "smallmoney";
  830. dbType = DbType.Currency;
  831. break;
  832. case SqlDbType.NChar:
  833. MetaParameter.TypeName = "nchar";
  834. dbType = DbType.StringFixedLength;
  835. MetaParameter.IsVariableSizeType = true;
  836. break;
  837. case SqlDbType.NText:
  838. MetaParameter.TypeName = "ntext";
  839. dbType = DbType.String;
  840. MetaParameter.IsVariableSizeType = true;
  841. break;
  842. case SqlDbType.NVarChar:
  843. MetaParameter.TypeName = "nvarchar";
  844. dbType = DbType.String;
  845. MetaParameter.IsVariableSizeType = true;
  846. break;
  847. case SqlDbType.Real:
  848. MetaParameter.TypeName = "real";
  849. dbType = DbType.Single;
  850. break;
  851. case SqlDbType.SmallInt:
  852. MetaParameter.TypeName = "smallint";
  853. dbType = DbType.Int16;
  854. break;
  855. case SqlDbType.Text:
  856. MetaParameter.TypeName = "text";
  857. dbType = DbType.AnsiString;
  858. MetaParameter.IsVariableSizeType = true;
  859. break;
  860. case SqlDbType.VarChar:
  861. MetaParameter.TypeName = "varchar";
  862. dbType = DbType.AnsiString;
  863. MetaParameter.IsVariableSizeType = true;
  864. break;
  865. case SqlDbType.TinyInt:
  866. MetaParameter.TypeName = "tinyint";
  867. dbType = DbType.Byte;
  868. break;
  869. case SqlDbType.UniqueIdentifier:
  870. MetaParameter.TypeName = "uniqueidentifier";
  871. dbType = DbType.Guid;
  872. break;
  873. case SqlDbType.Variant:
  874. MetaParameter.TypeName = "sql_variant";
  875. dbType = DbType.Object;
  876. break;
  877. #if NET_2_0
  878. case SqlDbType.Xml:
  879. MetaParameter.TypeName = "xml";
  880. dbType = DbType.Xml;
  881. MetaParameter.IsVariableSizeType = true;
  882. break;
  883. #endif
  884. default:
  885. string exception = String.Format ("No mapping exists from SqlDbType {0} to a known DbType.", type);
  886. throw new ArgumentOutOfRangeException ("SqlDbType", exception);
  887. }
  888. sqlDbType = type;
  889. }
  890. public override string ToString()
  891. {
  892. return ParameterName;
  893. }
  894. object GetFrameworkValue (object rawValue, ref bool updated)
  895. {
  896. object tdsValue;
  897. updated = typeChanged || updated;
  898. if (updated) {
  899. tdsValue = SqlTypeToFrameworkType (rawValue);
  900. typeChanged = false;
  901. } else
  902. tdsValue = null;
  903. return tdsValue;
  904. }
  905. // TODO: Code copied from SqlDataReader, need a better approach
  906. object GetSqlValue (object value)
  907. {
  908. if (value == null)
  909. return value;
  910. switch (sqlDbType) {
  911. case SqlDbType.BigInt:
  912. if (value == DBNull.Value)
  913. return SqlInt64.Null;
  914. return (SqlInt64) ((long) value);
  915. case SqlDbType.Binary:
  916. case SqlDbType.Image:
  917. case SqlDbType.VarBinary:
  918. case SqlDbType.Timestamp:
  919. if (value == DBNull.Value)
  920. return SqlBinary.Null;
  921. return (SqlBinary) (byte[]) value;
  922. case SqlDbType.Bit:
  923. if (value == DBNull.Value)
  924. return SqlBoolean.Null;
  925. return (SqlBoolean) ((bool) value);
  926. case SqlDbType.Char:
  927. case SqlDbType.NChar:
  928. case SqlDbType.NText:
  929. case SqlDbType.NVarChar:
  930. case SqlDbType.Text:
  931. case SqlDbType.VarChar:
  932. if (value == DBNull.Value)
  933. return SqlString.Null;
  934. string str;
  935. Type type = value.GetType ();
  936. if (type == typeof (char))
  937. str = value.ToString ();
  938. else if (type == typeof (char[]))
  939. str = new String ((char[])value);
  940. else
  941. str = ((string)value);
  942. return (SqlString) str;
  943. case SqlDbType.DateTime:
  944. case SqlDbType.SmallDateTime:
  945. if (value == DBNull.Value)
  946. return SqlDateTime.Null;
  947. return (SqlDateTime) ((DateTime) value);
  948. case SqlDbType.Decimal:
  949. if (value == DBNull.Value)
  950. return SqlDecimal.Null;
  951. if (value is TdsBigDecimal)
  952. return SqlDecimal.FromTdsBigDecimal ((TdsBigDecimal) value);
  953. return (SqlDecimal) ((decimal) value);
  954. case SqlDbType.Float:
  955. if (value == DBNull.Value)
  956. return SqlDouble.Null;
  957. return (SqlDouble) ((double) value);
  958. case SqlDbType.Int:
  959. if (value == DBNull.Value)
  960. return SqlInt32.Null;
  961. return (SqlInt32) ((int) value);
  962. case SqlDbType.Money:
  963. case SqlDbType.SmallMoney:
  964. if (value == DBNull.Value)
  965. return SqlMoney.Null;
  966. return (SqlMoney) ((decimal) value);
  967. case SqlDbType.Real:
  968. if (value == DBNull.Value)
  969. return SqlSingle.Null;
  970. return (SqlSingle) ((float) value);
  971. case SqlDbType.UniqueIdentifier:
  972. if (value == DBNull.Value)
  973. return SqlGuid.Null;
  974. return (SqlGuid) ((Guid) value);
  975. case SqlDbType.SmallInt:
  976. if (value == DBNull.Value)
  977. return SqlInt16.Null;
  978. return (SqlInt16) ((short) value);
  979. case SqlDbType.TinyInt:
  980. if (value == DBNull.Value)
  981. return SqlByte.Null;
  982. return (SqlByte) ((byte) value);
  983. #if NET_2_0
  984. case SqlDbType.Xml:
  985. if (value == DBNull.Value)
  986. return SqlXml.Null;
  987. return (SqlXml) value;
  988. #endif
  989. default:
  990. throw new NotImplementedException ("Type '" + sqlDbType + "' not implemented.");
  991. }
  992. }
  993. object SqlTypeToFrameworkType (object value)
  994. {
  995. INullable nullable = value as INullable;
  996. if (nullable == null)
  997. return ConvertToFrameworkType (value);
  998. if (nullable.IsNull)
  999. return DBNull.Value;
  1000. Type type = value.GetType ();
  1001. // Map to .net type, as Mono TDS respects only types from .net
  1002. if (typeof (SqlString) == type) {
  1003. return ((SqlString) value).Value;
  1004. }
  1005. if (typeof (SqlInt16) == type) {
  1006. return ((SqlInt16) value).Value;
  1007. }
  1008. if (typeof (SqlInt32) == type) {
  1009. return ((SqlInt32) value).Value;
  1010. }
  1011. if (typeof (SqlDateTime) == type) {
  1012. return ((SqlDateTime) value).Value;
  1013. }
  1014. if (typeof (SqlInt64) == type) {
  1015. return ((SqlInt64) value).Value;
  1016. }
  1017. if (typeof (SqlBinary) == type) {
  1018. return ((SqlBinary) value).Value;
  1019. }
  1020. #if NET_2_0
  1021. if (typeof (SqlBytes) == type) {
  1022. return ((SqlBytes) value).Value;
  1023. }
  1024. if (typeof (SqlChars) == type) {
  1025. return ((SqlChars) value).Value;
  1026. }
  1027. #endif
  1028. if (typeof (SqlBoolean) == type) {
  1029. return ((SqlBoolean) value).Value;
  1030. }
  1031. if (typeof (SqlByte) == type) {
  1032. return ((SqlByte) value).Value;
  1033. }
  1034. if (typeof (SqlDecimal) == type) {
  1035. return ((SqlDecimal) value).Value;
  1036. }
  1037. if (typeof (SqlDouble) == type) {
  1038. return ((SqlDouble) value).Value;
  1039. }
  1040. if (typeof (SqlGuid) == type) {
  1041. return ((SqlGuid) value).Value;
  1042. }
  1043. if (typeof (SqlMoney) == type) {
  1044. return ((SqlMoney) value).Value;
  1045. }
  1046. if (typeof (SqlSingle) == type) {
  1047. return ((SqlSingle) value).Value;
  1048. }
  1049. return value;
  1050. }
  1051. internal object ConvertToFrameworkType (object value)
  1052. {
  1053. if (value == null || value == DBNull.Value)
  1054. return value;
  1055. if (sqlDbType == SqlDbType.Variant)
  1056. return metaParameter.Value;
  1057. Type frameworkType = SystemType;
  1058. if (frameworkType == null)
  1059. throw new NotImplementedException ("Type Not Supported : " + sqlDbType.ToString());
  1060. Type valueType = value.GetType ();
  1061. if (valueType == frameworkType)
  1062. return value;
  1063. #if NET_2_0
  1064. object sqlvalue = null;
  1065. try {
  1066. sqlvalue = ConvertToFrameworkType (value, frameworkType);
  1067. } catch (FormatException ex) {
  1068. throw new FormatException (string.Format (CultureInfo.InvariantCulture,
  1069. "Parameter value could not be converted from {0} to {1}.",
  1070. valueType.Name, frameworkType.Name), ex);
  1071. }
  1072. return sqlvalue;
  1073. #else
  1074. return ConvertToFrameworkType (value, frameworkType);
  1075. #endif
  1076. }
  1077. object ConvertToFrameworkType (object value, Type frameworkType)
  1078. {
  1079. object sqlvalue = Convert.ChangeType (value, frameworkType);
  1080. switch (sqlDbType) {
  1081. case SqlDbType.Money:
  1082. case SqlDbType.SmallMoney:
  1083. sqlvalue = Decimal.Round ((decimal) sqlvalue, 4);
  1084. break;
  1085. }
  1086. return sqlvalue;
  1087. }
  1088. #if NET_2_0
  1089. public override void ResetDbType ()
  1090. {
  1091. InferSqlType (Value);
  1092. }
  1093. public void ResetSqlDbType ()
  1094. {
  1095. InferSqlType (Value);
  1096. }
  1097. #endif // NET_2_0
  1098. #endregion // Methods
  1099. }
  1100. }