DataColumn.cs 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959
  1. //------------------------------------------------------------------------------
  2. // <copyright file="DataColumn.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">[....]</owner>
  6. // <owner current="true" primary="false">[....]</owner>
  7. //------------------------------------------------------------------------------
  8. namespace System.Data {
  9. using System;
  10. using System.Xml;
  11. using System.Data.Common;
  12. using System.ComponentModel;
  13. using System.Diagnostics;
  14. using System.Collections;
  15. using System.Globalization;
  16. using System.Data.SqlTypes;
  17. using System.Xml.Serialization;
  18. using System.Collections.Generic;
  19. using System.Runtime.CompilerServices;
  20. /// <devdoc>
  21. /// <para>
  22. /// Represents one column of data in a <see cref='System.Data.DataTable'/>.
  23. /// </para>
  24. /// </devdoc>
  25. [
  26. ToolboxItem(false),
  27. DesignTimeVisible(false),
  28. DefaultProperty("ColumnName"),
  29. Editor("Microsoft.VSDesigner.Data.Design.DataColumnEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
  30. ]
  31. public class DataColumn : MarshalByValueComponent {
  32. // properties
  33. private bool allowNull = true;
  34. private string caption = null;
  35. private string _columnName = null;
  36. private Type dataType = null;
  37. private StorageType _storageType;
  38. internal object defaultValue = DBNull.Value; // DefaultValue Converter
  39. private DataSetDateTime _dateTimeMode = DataSetDateTime.UnspecifiedLocal;
  40. private DataExpression expression = null;
  41. private int maxLength = -1;
  42. private int _ordinal = -1;
  43. private bool readOnly = false;
  44. internal Index sortIndex = null;
  45. internal DataTable table = null;
  46. private bool unique = false;
  47. internal MappingType columnMapping = MappingType.Element;
  48. internal int _hashCode;
  49. internal int errors;
  50. private bool isSqlType = false;
  51. private bool implementsINullable = false;
  52. private bool implementsIChangeTracking = false;
  53. private bool implementsIRevertibleChangeTracking = false;
  54. private bool implementsIXMLSerializable = false;
  55. private bool defaultValueIsNull = true;
  56. // list of columns whose expression consume values from this column
  57. internal List<DataColumn> dependentColumns = null;
  58. // collections
  59. internal PropertyCollection extendedProperties = null;
  60. // events
  61. private PropertyChangedEventHandler onPropertyChangingDelegate = null;
  62. // state
  63. private DataStorage _storage;
  64. /// <summary>represents current value to return, usage pattern is .get_Current then MoveAfter</summary>
  65. private AutoIncrementValue autoInc;
  66. //
  67. // The _columnClass member is the class for the unfoliated virtual nodes in the XML.
  68. //
  69. internal string _columnUri = null;
  70. private string _columnPrefix = "";
  71. internal string encodedColumnName = null;
  72. //
  73. internal string dttype = ""; // The type specified in dt:type attribute
  74. internal SimpleType simpleType = null;
  75. private static int _objectTypeCount; // Bid counter
  76. private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
  77. /// <devdoc>
  78. /// <para>
  79. /// Initializes a new instance of a <see cref='System.Data.DataColumn'/>
  80. /// class.
  81. /// </para>
  82. /// </devdoc>
  83. public DataColumn() : this(null, typeof(string), null, MappingType.Element) {
  84. }
  85. /// <devdoc>
  86. /// <para>
  87. /// Inititalizes a new instance of the <see cref='System.Data.DataColumn'/> class
  88. /// using the specified column name.
  89. /// </para>
  90. /// </devdoc>
  91. public DataColumn(string columnName) : this(columnName, typeof(string), null, MappingType.Element) {
  92. }
  93. /// <devdoc>
  94. /// <para>
  95. /// Inititalizes a new instance of the <see cref='System.Data.DataColumn'/> class
  96. /// using the specified column name and data type.
  97. /// </para>
  98. /// </devdoc>
  99. public DataColumn(string columnName, Type dataType) : this(columnName, dataType, null, MappingType.Element) {
  100. }
  101. /// <devdoc>
  102. /// <para>
  103. /// Initializes a new instance
  104. /// of the <see cref='System.Data.DataColumn'/> class
  105. /// using the specified name, data type, and expression.
  106. /// </para>
  107. /// </devdoc>
  108. public DataColumn(string columnName, Type dataType, string expr) : this(columnName, dataType, expr, MappingType.Element) {
  109. }
  110. /// <devdoc>
  111. /// <para>
  112. /// Initializes a new instance of the <see cref='System.Data.DataColumn'/> class
  113. /// using
  114. /// the specified name, data type, expression, and value that determines whether the
  115. /// column is an attribute.
  116. /// </para>
  117. /// </devdoc>
  118. public DataColumn(string columnName, Type dataType, string expr, MappingType type) {
  119. GC.SuppressFinalize(this);
  120. Bid.Trace("<ds.DataColumn.DataColumn|API> %d#, columnName='%ls', expr='%ls', type=%d{ds.MappingType}\n",
  121. ObjectID, columnName, expr, (int)type);
  122. if (dataType == null) {
  123. throw ExceptionBuilder.ArgumentNull("dataType");
  124. }
  125. StorageType typeCode = DataStorage.GetStorageType(dataType);
  126. if (DataStorage.ImplementsINullableValue(typeCode, dataType)) {
  127. throw ExceptionBuilder.ColumnTypeNotSupported();
  128. }
  129. _columnName = columnName ?? string.Empty;
  130. SimpleType stype = SimpleType.CreateSimpleType(typeCode, dataType);
  131. if (null != stype) {
  132. this.SimpleType = stype;
  133. }
  134. UpdateColumnType(dataType, typeCode);
  135. if ((null != expr) && (0 < expr.Length)) {
  136. // @perfnote: its a performance hit to set Expression to the empty str when we know it will come out null
  137. this.Expression = expr;
  138. }
  139. this.columnMapping = type;
  140. }
  141. private void UpdateColumnType(Type type, StorageType typeCode) {
  142. dataType = type;
  143. _storageType = typeCode;
  144. if (StorageType.DateTime != typeCode) { // revert _dateTimeMode back to default, when column type is changed
  145. _dateTimeMode = DataSetDateTime.UnspecifiedLocal;
  146. }
  147. DataStorage.ImplementsInterfaces(
  148. typeCode, type,
  149. out isSqlType,
  150. out implementsINullable,
  151. out implementsIXMLSerializable,
  152. out implementsIChangeTracking,
  153. out implementsIRevertibleChangeTracking);
  154. if (!isSqlType && implementsINullable) {
  155. SqlUdtStorage.GetStaticNullForUdtType(type);
  156. }
  157. }
  158. // PUBLIC PROPERTIES
  159. /// <devdoc>
  160. /// <para>
  161. /// Gets or sets a value indicating whether null
  162. /// values are
  163. /// allowed in this column for rows belonging to the table.
  164. /// </para>
  165. /// </devdoc>
  166. [
  167. ResCategoryAttribute(Res.DataCategory_Data),
  168. DefaultValue(true),
  169. ResDescriptionAttribute(Res.DataColumnAllowNullDescr)
  170. ]
  171. public bool AllowDBNull {
  172. get {
  173. return allowNull;
  174. }
  175. set {
  176. IntPtr hscp;
  177. Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_AllowDBNull|API> %d#, %d{bool}\n", ObjectID, value);
  178. try {
  179. if (allowNull != value) {
  180. if (table != null) {
  181. if (!value && table.EnforceConstraints)
  182. CheckNotAllowNull();
  183. }
  184. this.allowNull = value;
  185. }
  186. //
  187. }
  188. finally {
  189. Bid.ScopeLeave(ref hscp);
  190. }
  191. }
  192. }
  193. /// <devdoc>
  194. /// <para>
  195. /// Gets or
  196. /// sets a value indicating whether the column automatically increments the value of the column for new
  197. /// rows added to the table.
  198. /// </para>
  199. /// </devdoc>
  200. [
  201. ResCategoryAttribute(Res.DataCategory_Data),
  202. RefreshProperties(RefreshProperties.All),
  203. DefaultValue(false),
  204. ResDescriptionAttribute(Res.DataColumnAutoIncrementDescr)
  205. ]
  206. public bool AutoIncrement {
  207. get {
  208. return ((null != autoInc) && (autoInc.Auto));
  209. }
  210. set {
  211. Bid.Trace("<ds.DataColumn.set_AutoIncrement|API> %d#, %d{bool}\n", ObjectID, value);
  212. if (this.AutoIncrement != value) {
  213. if (value) {
  214. if (expression != null) {
  215. throw ExceptionBuilder.AutoIncrementAndExpression();
  216. }
  217. // if (defaultValue != null && defaultValue != DBNull.Value) {
  218. if (!DefaultValueIsNull) {
  219. throw ExceptionBuilder.AutoIncrementAndDefaultValue();
  220. }
  221. if (!IsAutoIncrementType(DataType)) {
  222. if (HasData) {
  223. throw ExceptionBuilder.AutoIncrementCannotSetIfHasData(DataType.Name);
  224. }
  225. DataType = typeof(int);
  226. }
  227. }
  228. this.AutoInc.Auto = value;
  229. }
  230. }
  231. }
  232. internal object AutoIncrementCurrent {
  233. get { return ((null != this.autoInc) ? this.autoInc.Current : this.AutoIncrementSeed); }
  234. set {
  235. if ((System.Numerics.BigInteger)this.AutoIncrementSeed != BigIntegerStorage.ConvertToBigInteger(value, this.FormatProvider)) {
  236. this.AutoInc.SetCurrent(value, this.FormatProvider);
  237. }
  238. }
  239. }
  240. internal AutoIncrementValue AutoInc {
  241. get {
  242. return (this.autoInc ?? (this.autoInc = ((this.DataType == typeof(System.Numerics.BigInteger))
  243. ? (AutoIncrementValue)new AutoIncrementBigInteger()
  244. : new AutoIncrementInt64())));
  245. }
  246. }
  247. /// <devdoc>
  248. /// <para>
  249. /// Gets
  250. /// or sets the starting value for a column that has its
  251. /// <see cref='System.Data.DataColumn.AutoIncrement'/> property
  252. /// set to <see langword='true'/>
  253. /// .
  254. /// </para>
  255. /// </devdoc>
  256. [
  257. ResCategoryAttribute(Res.DataCategory_Data),
  258. DefaultValue((Int64)0),
  259. ResDescriptionAttribute(Res.DataColumnAutoIncrementSeedDescr)
  260. ]
  261. public Int64 AutoIncrementSeed {
  262. get {
  263. return ((null != this.autoInc) ? this.autoInc.Seed : 0L);
  264. }
  265. set {
  266. Bid.Trace("<ds.DataColumn.set_AutoIncrementSeed|API> %d#, %I64d\n", ObjectID, value);
  267. if (this.AutoIncrementSeed != value) {
  268. this.AutoInc.Seed = value;
  269. }
  270. }
  271. }
  272. /// <devdoc>
  273. /// <para>
  274. /// Gets or sets the increment used by a column with its <see cref='System.Data.DataColumn.AutoIncrement'/>
  275. /// property set to <see langword='true'/>
  276. /// .
  277. /// </para>
  278. /// </devdoc>
  279. [
  280. ResCategoryAttribute(Res.DataCategory_Data),
  281. DefaultValue((Int64)1),
  282. ResDescriptionAttribute(Res.DataColumnAutoIncrementStepDescr)
  283. ]
  284. public Int64 AutoIncrementStep {
  285. get {
  286. return ((null != this.autoInc) ? this.autoInc.Step : 1L);
  287. }
  288. set {
  289. Bid.Trace("<ds.DataColumn.set_AutoIncrementStep|API> %d#, %I64d\n", ObjectID, value);
  290. if (this.AutoIncrementStep != value) {
  291. this.AutoInc.Step = value;
  292. }
  293. }
  294. }
  295. /// <devdoc>
  296. /// <para>
  297. /// Gets or sets
  298. /// the caption for this column.
  299. /// </para>
  300. /// </devdoc>
  301. [
  302. ResCategoryAttribute(Res.DataCategory_Data),
  303. ResDescriptionAttribute(Res.DataColumnCaptionDescr)
  304. ]
  305. public string Caption {
  306. get {
  307. return (caption != null) ? caption : _columnName;
  308. }
  309. set {
  310. if (value == null)
  311. value = "";
  312. if (caption == null || String.Compare(caption, value, true, Locale) != 0) {
  313. caption = value;
  314. }
  315. }
  316. }
  317. /// <devdoc>
  318. /// <para>
  319. /// Resets the <see cref='System.Data.DataColumn.Caption'/> property to its previous value, or
  320. /// to <see langword='null'/> .
  321. /// </para>
  322. /// </devdoc>
  323. private void ResetCaption() {
  324. if (caption != null) {
  325. caption = null;
  326. }
  327. }
  328. /// <devdoc>
  329. /// <para>
  330. /// Gets a value indicating whether the <see cref='System.Data.DataColumn.Caption'/> has been explicitly set.
  331. /// </para>
  332. /// </devdoc>
  333. private bool ShouldSerializeCaption() {
  334. return (caption != null);
  335. }
  336. /// <devdoc>
  337. /// <para>
  338. /// Gets or sets the name of the column within the <see cref='System.Data.DataColumnCollection'/>.
  339. /// </para>
  340. /// </devdoc>
  341. [
  342. RefreshProperties(RefreshProperties.All),
  343. ResCategoryAttribute(Res.DataCategory_Data),
  344. DefaultValue(""),
  345. ResDescriptionAttribute(Res.DataColumnColumnNameDescr)
  346. ]
  347. public string ColumnName {
  348. get {
  349. return _columnName;
  350. }
  351. set {
  352. IntPtr hscp;
  353. Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_ColumnName|API> %d#, '%ls'\n", ObjectID, value);
  354. try {
  355. if (value == null) {
  356. value = "";
  357. }
  358. if (String.Compare(_columnName, value, true, Locale) != 0) {
  359. if (table != null) {
  360. if (value.Length == 0)
  361. throw ExceptionBuilder.ColumnNameRequired();
  362. table.Columns.RegisterColumnName(value, this);
  363. if (_columnName.Length != 0)
  364. table.Columns.UnregisterName(_columnName);
  365. }
  366. RaisePropertyChanging("ColumnName");
  367. _columnName = value;
  368. encodedColumnName = null;
  369. if (table != null) {
  370. table.Columns.OnColumnPropertyChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this));
  371. }
  372. }
  373. else if (_columnName != value) {
  374. RaisePropertyChanging("ColumnName");
  375. _columnName = value;
  376. encodedColumnName = null;
  377. if (table != null) {
  378. table.Columns.OnColumnPropertyChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this));
  379. }
  380. }
  381. }
  382. finally {
  383. Bid.ScopeLeave(ref hscp);
  384. }
  385. }
  386. }
  387. internal string EncodedColumnName {
  388. get {
  389. if (this.encodedColumnName == null) {
  390. this.encodedColumnName = XmlConvert.EncodeLocalName(this.ColumnName);
  391. }
  392. Debug.Assert(this.encodedColumnName != null && this.encodedColumnName.Length != 0);
  393. return this.encodedColumnName;
  394. }
  395. }
  396. internal IFormatProvider FormatProvider {
  397. get {
  398. // used for formating/parsing not comparing
  399. return ((null != table) ? table.FormatProvider : CultureInfo.CurrentCulture);
  400. }
  401. }
  402. internal CultureInfo Locale {
  403. get {
  404. // used for comparing not formating/parsing
  405. return ((null != table) ? table.Locale : CultureInfo.CurrentCulture);
  406. }
  407. }
  408. internal int ObjectID {
  409. get {
  410. return _objectID;
  411. }
  412. }
  413. [
  414. ResCategoryAttribute(Res.DataCategory_Data),
  415. DefaultValue(""),
  416. ResDescriptionAttribute(Res.DataColumnPrefixDescr)
  417. ]
  418. public string Prefix {
  419. get { return _columnPrefix; }
  420. set {
  421. if (value == null)
  422. value = "";
  423. Bid.Trace("<ds.DataColumn.set_Prefix|API> %d#, '%ls'\n", ObjectID, value);
  424. if ((XmlConvert.DecodeName(value) == value) && (XmlConvert.EncodeName(value) != value))
  425. throw ExceptionBuilder.InvalidPrefix(value);
  426. _columnPrefix = value;
  427. }
  428. }
  429. // Return the field value as a string. If the field value is NULL, then NULL is return.
  430. // If the column type is string and it's value is empty, then the empty string is returned.
  431. // If the column type is not string, or the column type is string and the value is not empty string, then a non-empty string is returned
  432. // This method does not throw any formatting exceptions, since we can always format the field value to a string.
  433. internal string GetColumnValueAsString(DataRow row, DataRowVersion version) {
  434. object objValue = this[row.GetRecordFromVersion(version)];
  435. if (DataStorage.IsObjectNull(objValue)) {
  436. return null;
  437. }
  438. string value = ConvertObjectToXml(objValue);
  439. Debug.Assert(value != null);
  440. return value;
  441. }
  442. /// <devdoc>
  443. /// Whether this column computes values.
  444. /// </devdoc>
  445. internal bool Computed {
  446. get {
  447. return this.expression != null;
  448. }
  449. }
  450. /// <devdoc>
  451. /// The internal expression object that computes the values.
  452. /// </devdoc>
  453. internal DataExpression DataExpression {
  454. get {
  455. return this.expression;
  456. }
  457. }
  458. /// <devdoc>
  459. /// <para>
  460. /// The type
  461. /// of data stored in thecolumn.
  462. /// </para>
  463. /// </devdoc>
  464. [
  465. ResCategoryAttribute(Res.DataCategory_Data),
  466. DefaultValue(typeof(string)),
  467. RefreshProperties(RefreshProperties.All),
  468. TypeConverter(typeof(ColumnTypeConverter)),
  469. ResDescriptionAttribute(Res.DataColumnDataTypeDescr)
  470. ]
  471. public Type DataType {
  472. get {
  473. return dataType;
  474. }
  475. set {
  476. if (dataType != value) {
  477. if (HasData) {
  478. throw ExceptionBuilder.CantChangeDataType();
  479. }
  480. if (value == null) {
  481. throw ExceptionBuilder.NullDataType();
  482. }
  483. StorageType typeCode = DataStorage.GetStorageType(value);
  484. if (DataStorage.ImplementsINullableValue(typeCode, value)) {
  485. throw ExceptionBuilder.ColumnTypeNotSupported();
  486. }
  487. if (table != null && IsInRelation()) {
  488. throw ExceptionBuilder.ColumnsTypeMismatch();
  489. }
  490. if (typeCode == StorageType.BigInteger && this.expression != null)
  491. {
  492. throw ExprException.UnsupportedDataType(value);
  493. }
  494. // If the DefualtValue is different from the Column DataType, we will coerce the value to the DataType
  495. if (!DefaultValueIsNull) {
  496. try {
  497. if (this.defaultValue is System.Numerics.BigInteger) {
  498. this.defaultValue = BigIntegerStorage.ConvertFromBigInteger((System.Numerics.BigInteger)this.defaultValue, value, this.FormatProvider);
  499. }
  500. else if (typeof(System.Numerics.BigInteger) == value) {
  501. this.defaultValue = BigIntegerStorage.ConvertToBigInteger(this.defaultValue, this.FormatProvider);
  502. }
  503. else if (typeof(string) == value) { // since string types can be null in value! DO NOT REMOVE THIS
  504. defaultValue = DefaultValue.ToString();
  505. }
  506. else if (typeof(SqlString) == value) { // since string types can be null in value! DO NOT REMOVE THIS
  507. defaultValue = SqlConvert.ConvertToSqlString(DefaultValue);
  508. }
  509. else if (typeof(object) != value) {
  510. DefaultValue = SqlConvert.ChangeTypeForDefaultValue(DefaultValue, value, FormatProvider);
  511. }
  512. }
  513. catch (InvalidCastException ex) {
  514. throw ExceptionBuilder.DefaultValueDataType(ColumnName, DefaultValue.GetType(), value, ex);
  515. }
  516. catch (FormatException ex) {
  517. throw ExceptionBuilder.DefaultValueDataType(ColumnName, DefaultValue.GetType(), value, ex);
  518. }
  519. }
  520. if (this.ColumnMapping == MappingType.SimpleContent)
  521. if (value == typeof(Char))
  522. throw ExceptionBuilder.CannotSetSimpleContentType(ColumnName, value);
  523. SimpleType = SimpleType.CreateSimpleType(typeCode, value);
  524. if (StorageType.String == typeCode) {
  525. maxLength = -1;
  526. }
  527. UpdateColumnType(value, typeCode);
  528. XmlDataType = null;
  529. if (AutoIncrement) {
  530. if (!IsAutoIncrementType(value)) {
  531. AutoIncrement = false;
  532. }
  533. if (null != this.autoInc) {
  534. // if you already have data you can't change the data type
  535. // if you don't have data - you wouldn't have incremented AutoIncrementCurrent.
  536. AutoIncrementValue inc = this.autoInc;
  537. this.autoInc = null;
  538. this.AutoInc.Auto = inc.Auto; // recreate with correct datatype
  539. this.AutoInc.Seed = inc.Seed;
  540. this.AutoInc.Step = inc.Step;
  541. if (this.autoInc.DataType == inc.DataType) {
  542. this.autoInc.Current = inc.Current;
  543. }
  544. else if (inc.DataType == typeof(Int64)) {
  545. this.AutoInc.Current = (System.Numerics.BigInteger)(long)inc.Current;
  546. }
  547. else {
  548. this.AutoInc.Current = checked((long)(System.Numerics.BigInteger)inc.Current);
  549. }
  550. }
  551. }
  552. }
  553. }
  554. }
  555. [
  556. ResCategoryAttribute(Res.DataCategory_Data),
  557. DefaultValue(DataSetDateTime.UnspecifiedLocal),
  558. RefreshProperties(RefreshProperties.All),
  559. ResDescriptionAttribute(Res.DataColumnDateTimeModeDescr)
  560. ]
  561. public DataSetDateTime DateTimeMode {
  562. get {
  563. return _dateTimeMode;
  564. }
  565. set {
  566. if (_dateTimeMode != value) {
  567. if (DataType != typeof(DateTime) && value != DataSetDateTime.UnspecifiedLocal) { //Check for column being DateTime. If the column is not DateTime make sure the value that is being is only the default[UnspecifiedLocal].
  568. throw ExceptionBuilder.CannotSetDateTimeModeForNonDateTimeColumns();
  569. }
  570. switch (value) {
  571. case DataSetDateTime.Utc:
  572. case DataSetDateTime.Local:
  573. if (HasData) {
  574. throw ExceptionBuilder.CantChangeDateTimeMode(_dateTimeMode, value);
  575. }
  576. break;
  577. case DataSetDateTime.Unspecified:
  578. case DataSetDateTime.UnspecifiedLocal:
  579. if (_dateTimeMode == DataSetDateTime.Unspecified || _dateTimeMode == DataSetDateTime.UnspecifiedLocal) {
  580. break;
  581. }
  582. if (HasData) {
  583. throw ExceptionBuilder.CantChangeDateTimeMode(_dateTimeMode, value);
  584. }
  585. break;
  586. default:
  587. throw ExceptionBuilder.InvalidDateTimeMode(value);
  588. }
  589. _dateTimeMode = value;
  590. }
  591. }
  592. }
  593. /// <devdoc>
  594. /// <para>Gets or sets the default value for the
  595. /// column when creating new rows.</para>
  596. /// </devdoc>
  597. [
  598. ResCategoryAttribute(Res.DataCategory_Data),
  599. ResDescriptionAttribute(Res.DataColumnDefaultValueDescr),
  600. TypeConverter(typeof(DefaultValueTypeConverter))
  601. ]
  602. public object DefaultValue {
  603. get {
  604. Debug.Assert(defaultValue != null, "It should not have been set to null.");
  605. if (defaultValue == DBNull.Value && this.implementsINullable) { // for perf I dont access property
  606. if (_storage != null)
  607. defaultValue = _storage.NullValue;
  608. else if (this.isSqlType)
  609. defaultValue = SqlConvert.ChangeTypeForDefaultValue(defaultValue, this.dataType, FormatProvider);
  610. else if (this.implementsINullable) {
  611. System.Reflection.PropertyInfo propInfo = this.dataType.GetProperty("Null", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
  612. if (propInfo != null)
  613. defaultValue = propInfo.GetValue(null, null);
  614. }
  615. }
  616. return defaultValue;
  617. }
  618. set {
  619. Bid.Trace("<ds.DataColumn.set_DefaultValue|API> %d#\n", ObjectID);
  620. if (defaultValue == null || !DefaultValue.Equals(value)) {
  621. if (AutoIncrement) {
  622. throw ExceptionBuilder.DefaultValueAndAutoIncrement();
  623. }
  624. object newDefaultValue = (value == null) ? DBNull.Value : value;
  625. if (newDefaultValue != DBNull.Value && DataType != typeof(Object)) {
  626. // If the DefualtValue is different from the Column DataType, we will coerce the value to the DataType
  627. try {
  628. newDefaultValue = SqlConvert.ChangeTypeForDefaultValue(newDefaultValue, DataType, FormatProvider);
  629. }
  630. catch (InvalidCastException ex) {
  631. throw ExceptionBuilder.DefaultValueColumnDataType(ColumnName, newDefaultValue.GetType(), DataType, ex);
  632. }
  633. }
  634. defaultValue = newDefaultValue;
  635. // SQL BU Defect Tracking 401640: should not assign any value until conversion is successful.
  636. defaultValueIsNull = ((newDefaultValue == DBNull.Value) || (this.ImplementsINullable && DataStorage.IsObjectSqlNull(newDefaultValue))) ? true : false;
  637. }
  638. }
  639. }
  640. internal bool DefaultValueIsNull {
  641. get {
  642. return defaultValueIsNull;
  643. }
  644. }
  645. internal void BindExpression() {
  646. this.DataExpression.Bind(this.table);
  647. }
  648. /// <devdoc>
  649. /// <para>Gets
  650. /// or sets the expresssion used to either filter rows, calculate the column's
  651. /// value, or create an aggregate column.</para>
  652. /// </devdoc>
  653. [
  654. ResCategoryAttribute(Res.DataCategory_Data),
  655. RefreshProperties(RefreshProperties.All),
  656. DefaultValue(""),
  657. ResDescriptionAttribute(Res.DataColumnExpressionDescr)
  658. ]
  659. public string Expression {
  660. get {
  661. return (this.expression == null ? "" : this.expression.Expression);
  662. }
  663. set {
  664. IntPtr hscp;
  665. Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_Expression|API> %d#, '%ls'\n", ObjectID, value);
  666. if (value == null) {
  667. value = "";
  668. }
  669. try {
  670. DataExpression newExpression = null;
  671. if (value.Length > 0) {
  672. DataExpression testExpression = new DataExpression(this.table, value, this.dataType);
  673. if (testExpression.HasValue) {
  674. newExpression = testExpression;
  675. }
  676. }
  677. if (expression == null && newExpression != null) {
  678. if (AutoIncrement || Unique) {
  679. throw ExceptionBuilder.ExpressionAndUnique();
  680. }
  681. // We need to make sure the column is not involved in any Constriants
  682. if (table != null) {
  683. for (int i = 0; i < table.Constraints.Count; i++) {
  684. if (table.Constraints[i].ContainsColumn(this)) {
  685. throw ExceptionBuilder.ExpressionAndConstraint(this, table.Constraints[i]);
  686. }
  687. }
  688. }
  689. bool oldReadOnly = ReadOnly;
  690. try {
  691. ReadOnly = true;
  692. }
  693. catch (ReadOnlyException e) {
  694. ExceptionBuilder.TraceExceptionForCapture(e);
  695. ReadOnly = oldReadOnly;
  696. throw ExceptionBuilder.ExpressionAndReadOnly();
  697. }
  698. }
  699. // re-calculate the evaluation queue
  700. if (this.table != null) {
  701. if (newExpression != null && newExpression.DependsOn(this)) {
  702. throw ExceptionBuilder.ExpressionCircular();
  703. }
  704. HandleDependentColumnList(expression, newExpression);
  705. //hold onto oldExpression in case of error applying new Expression.
  706. DataExpression oldExpression = this.expression;
  707. this.expression = newExpression;
  708. // because the column is attached to a table we need to re-calc values
  709. try {
  710. if (newExpression == null) {
  711. for (int i = 0; i < table.RecordCapacity; i++) {
  712. InitializeRecord(i);
  713. }
  714. }
  715. else {
  716. this.table.EvaluateExpressions(this);
  717. }
  718. // SQLBU 501916: DataTable internal index is corrupted:'5'
  719. this.table.ResetInternalIndexes(this);
  720. this.table.EvaluateDependentExpressions(this);
  721. }
  722. catch (Exception e1) {
  723. //
  724. if (!ADP.IsCatchableExceptionType(e1)) {
  725. throw;
  726. }
  727. ExceptionBuilder.TraceExceptionForCapture(e1);
  728. try {
  729. // in the case of error we need to set the column expression to the old value
  730. this.expression = oldExpression;
  731. HandleDependentColumnList(newExpression, expression);
  732. if (oldExpression == null) {
  733. for (int i = 0; i < table.RecordCapacity; i++) {
  734. InitializeRecord(i);
  735. }
  736. }
  737. else {
  738. this.table.EvaluateExpressions(this);
  739. }
  740. this.table.ResetInternalIndexes(this);
  741. this.table.EvaluateDependentExpressions(this);
  742. }
  743. catch (Exception e2) {
  744. //
  745. if (!ADP.IsCatchableExceptionType(e2)) {
  746. throw;
  747. }
  748. ExceptionBuilder.TraceExceptionWithoutRethrow(e2);
  749. }
  750. throw;
  751. }
  752. }
  753. else {
  754. //if column is not attached to a table, just set.
  755. this.expression = newExpression;
  756. }
  757. }
  758. finally {
  759. Bid.ScopeLeave(ref hscp);
  760. }
  761. }
  762. }
  763. /// <devdoc>
  764. /// <para>Gets the collection of custom user information.</para>
  765. /// </devdoc>
  766. [
  767. ResCategoryAttribute(Res.DataCategory_Data),
  768. Browsable(false),
  769. ResDescriptionAttribute(Res.ExtendedPropertiesDescr)
  770. ]
  771. public PropertyCollection ExtendedProperties {
  772. get {
  773. if (extendedProperties == null) {
  774. extendedProperties = new PropertyCollection();
  775. }
  776. return extendedProperties;
  777. }
  778. }
  779. /// <devdoc>
  780. /// Indicates whether this column is now storing data.
  781. /// </devdoc>
  782. internal bool HasData {
  783. get {
  784. return (_storage != null);
  785. }
  786. }
  787. internal bool ImplementsINullable {
  788. get {
  789. return implementsINullable;
  790. }
  791. }
  792. internal bool ImplementsIChangeTracking {
  793. get {
  794. return implementsIChangeTracking;
  795. }
  796. }
  797. internal bool ImplementsIRevertibleChangeTracking {
  798. get {
  799. return implementsIRevertibleChangeTracking;
  800. }
  801. }
  802. internal bool IsCloneable {
  803. get {
  804. Debug.Assert(null != _storage, "no storage");
  805. return _storage.IsCloneable;
  806. }
  807. }
  808. internal bool IsStringType {
  809. get {
  810. Debug.Assert(null != _storage, "no storage");
  811. return _storage.IsStringType;
  812. }
  813. }
  814. internal bool IsValueType {
  815. get {
  816. Debug.Assert(null != _storage, "no storage");
  817. return _storage.IsValueType;
  818. }
  819. }
  820. internal bool IsSqlType {
  821. get {
  822. return isSqlType;
  823. }
  824. }
  825. private void SetMaxLengthSimpleType() {
  826. if (this.simpleType != null) {
  827. Debug.Assert(this.simpleType.CanHaveMaxLength(), "expected simpleType to be string");
  828. this.simpleType.MaxLength = maxLength;
  829. // check if we reset the simpleType back to plain string
  830. if (this.simpleType.IsPlainString()) {
  831. this.simpleType = null;
  832. }
  833. else {
  834. // Named Simple Type's Name should not be null
  835. if (this.simpleType.Name != null && this.dttype != null) {
  836. // if MaxLength is changed, we need to make namedsimpletype annonymous simpletype
  837. this.simpleType.ConvertToAnnonymousSimpleType();
  838. this.dttype = null;
  839. }
  840. }
  841. }
  842. else if (-1 < maxLength) {
  843. this.SimpleType = SimpleType.CreateLimitedStringType(maxLength);
  844. }
  845. }
  846. [
  847. ResCategoryAttribute(Res.DataCategory_Data),
  848. ResDescriptionAttribute(Res.DataColumnMaxLengthDescr),
  849. DefaultValue(-1)
  850. ]
  851. public int MaxLength {
  852. get {
  853. return maxLength;
  854. }
  855. set {
  856. IntPtr hscp;
  857. Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_MaxLength|API> %d#, %d\n", ObjectID, value);
  858. try {
  859. if (maxLength != value) {
  860. if (this.ColumnMapping == MappingType.SimpleContent) {
  861. throw ExceptionBuilder.CannotSetMaxLength2(this);
  862. }
  863. if ((DataType != typeof(string)) && (DataType != typeof(SqlString))) {
  864. throw ExceptionBuilder.HasToBeStringType(this);
  865. }
  866. int oldValue = maxLength;
  867. maxLength = Math.Max(value, -1);
  868. if (((oldValue < 0) || (value < oldValue)) && (null != table) && table.EnforceConstraints) {
  869. if (!CheckMaxLength()) {
  870. maxLength = oldValue;
  871. throw ExceptionBuilder.CannotSetMaxLength(this, value);
  872. }
  873. }
  874. SetMaxLengthSimpleType();
  875. }
  876. }
  877. finally {
  878. Bid.ScopeLeave(ref hscp);
  879. }
  880. }
  881. }
  882. [
  883. ResCategoryAttribute(Res.DataCategory_Data),
  884. ResDescriptionAttribute(Res.DataColumnNamespaceDescr)
  885. ]
  886. public string Namespace {
  887. get {
  888. if (_columnUri == null) {
  889. if (Table != null && columnMapping != MappingType.Attribute) {
  890. return Table.Namespace;
  891. }
  892. return "";
  893. }
  894. return _columnUri;
  895. }
  896. set {
  897. Bid.Trace("<ds.DataColumn.set_Namespace|API> %d#, '%ls'\n", ObjectID, value);
  898. if (_columnUri != value) {
  899. if (columnMapping != MappingType.SimpleContent) {
  900. RaisePropertyChanging("Namespace");
  901. _columnUri = value;
  902. }
  903. else if (value != this.Namespace) {
  904. throw ExceptionBuilder.CannotChangeNamespace(this.ColumnName);
  905. }
  906. }
  907. }
  908. }
  909. private bool ShouldSerializeNamespace() {
  910. return (_columnUri != null);
  911. }
  912. private void ResetNamespace() {
  913. this.Namespace = null;
  914. }
  915. /// <devdoc>
  916. /// <para>
  917. /// Gets the position of the column in the <see cref='System.Data.DataColumnCollection'/>
  918. /// collection.
  919. /// </para>
  920. /// </devdoc>
  921. [
  922. ResCategoryAttribute(Res.DataCategory_Data),
  923. Browsable(false),
  924. DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
  925. ResDescriptionAttribute(Res.DataColumnOrdinalDescr)
  926. ]
  927. public int Ordinal {
  928. get {
  929. return _ordinal;
  930. }
  931. }
  932. public void SetOrdinal(int ordinal) {
  933. if (_ordinal == -1) {
  934. throw ExceptionBuilder.ColumnNotInAnyTable();
  935. }
  936. if (this._ordinal != ordinal) {
  937. table.Columns.MoveTo(this, ordinal);
  938. }
  939. }
  940. internal void SetOrdinalInternal(int ordinal) {
  941. //
  942. if (this._ordinal != ordinal) {
  943. if (Unique && this._ordinal != -1 && ordinal == -1) {
  944. UniqueConstraint key = table.Constraints.FindKeyConstraint(this);
  945. if (key != null)
  946. table.Constraints.Remove(key);
  947. }
  948. // SQLBU 429176: remove the sortIndex when DataColumn is removed
  949. if ((null != sortIndex) && (-1 == ordinal)) {
  950. Debug.Assert(2 <= sortIndex.RefCount, "bad sortIndex refcount");
  951. sortIndex.RemoveRef();
  952. sortIndex.RemoveRef(); // second should remove it from index collection
  953. sortIndex = null;
  954. }
  955. int originalOrdinal = this._ordinal;
  956. this._ordinal = ordinal;
  957. if (originalOrdinal == -1 && this._ordinal != -1) {
  958. if (Unique) {
  959. UniqueConstraint key = new UniqueConstraint(this);
  960. table.Constraints.Add(key);
  961. }
  962. }
  963. }
  964. }
  965. /// <devdoc>
  966. /// <para>
  967. /// Gets or sets a value
  968. /// indicating whether the column allows changes once a row has been added to the table.
  969. /// </para>
  970. /// </devdoc>
  971. [
  972. ResCategoryAttribute(Res.DataCategory_Data),
  973. DefaultValue(false),
  974. ResDescriptionAttribute(Res.DataColumnReadOnlyDescr)
  975. ]
  976. public bool ReadOnly {
  977. get {
  978. return readOnly;
  979. }
  980. set {
  981. Bid.Trace("<ds.DataColumn.set_ReadOnly|API> %d#, %d{bool}\n", ObjectID, value);
  982. if (readOnly != value) {
  983. if (!value && expression != null) {
  984. throw ExceptionBuilder.ReadOnlyAndExpression();
  985. }
  986. this.readOnly = value;
  987. }
  988. }
  989. }
  990. [DebuggerBrowsable(DebuggerBrowsableState.Never)] // don't have debugger view expand this
  991. private Index SortIndex {
  992. get {
  993. if (sortIndex == null) {
  994. IndexField[] indexDesc = new IndexField[] { new IndexField(this, false) };
  995. sortIndex = table.GetIndex(indexDesc, DataViewRowState.CurrentRows, (IFilter)null);
  996. sortIndex.AddRef();
  997. }
  998. return sortIndex;
  999. }
  1000. }
  1001. /// <devdoc>
  1002. /// <para>
  1003. /// Gets the <see cref='System.Data.DataTable'/> to which the column belongs to.
  1004. /// </para>
  1005. /// </devdoc>
  1006. [
  1007. ResCategoryAttribute(Res.DataCategory_Data),
  1008. Browsable(false),
  1009. DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
  1010. ResDescriptionAttribute(Res.DataColumnDataTableDescr)
  1011. ]
  1012. public DataTable Table {
  1013. get {
  1014. return table;
  1015. }
  1016. }
  1017. /// <devdoc>
  1018. /// Internal mechanism for changing the table pointer.
  1019. /// </devdoc>
  1020. internal void SetTable(DataTable table) {
  1021. if (this.table != table) {
  1022. if (this.Computed)
  1023. if ((table == null) ||
  1024. (!table.fInitInProgress && ((table.DataSet == null) || (!table.DataSet.fIsSchemaLoading && !table.DataSet.fInitInProgress)))) {
  1025. // We need to re-bind all expression columns.
  1026. this.DataExpression.Bind(table);
  1027. }
  1028. if (Unique && this.table != null) {
  1029. UniqueConstraint constraint = table.Constraints.FindKeyConstraint(this);
  1030. if (constraint != null)
  1031. table.Constraints.CanRemove(constraint, true);
  1032. }
  1033. this.table = table;
  1034. _storage = null; // empty out storage for reuse.
  1035. }
  1036. }
  1037. private DataRow GetDataRow(int index) {
  1038. return table.recordManager[index];
  1039. }
  1040. /// <devdoc>
  1041. /// This is how data is pushed in and out of the column.
  1042. /// </devdoc>
  1043. internal object this[int record] {
  1044. get {
  1045. table.recordManager.VerifyRecord(record);
  1046. Debug.Assert(null != _storage, "null storage");
  1047. return _storage.Get(record);
  1048. }
  1049. set {
  1050. try {
  1051. table.recordManager.VerifyRecord(record);
  1052. Debug.Assert(null != _storage, "no storage");
  1053. Debug.Assert(null != value, "setting null, expecting dbnull");
  1054. _storage.Set(record, value);
  1055. Debug.Assert(null != this.table, "storage with no DataTable on column");
  1056. }
  1057. catch (Exception e) {
  1058. ExceptionBuilder.TraceExceptionForCapture(e);
  1059. throw ExceptionBuilder.SetFailed(value, this, DataType, e);
  1060. }
  1061. if (AutoIncrement) {
  1062. if (!_storage.IsNull(record)) {
  1063. this.AutoInc.SetCurrentAndIncrement(_storage.Get(record));
  1064. }
  1065. }
  1066. if (Computed) {// if and only if it is Expression column, we will cache LastChangedColumn, otherwise DO NOT
  1067. DataRow dr = GetDataRow(record);
  1068. if (dr != null) {
  1069. // at initialization time (datatable.NewRow(), we would fill the storage with default value, but at that time we wont have datarow)
  1070. dr.LastChangedColumn = this;
  1071. }
  1072. }
  1073. }
  1074. }
  1075. internal void InitializeRecord(int record) {
  1076. Debug.Assert(null != _storage, "no storage");
  1077. _storage.Set(record, DefaultValue);
  1078. }
  1079. internal void SetValue(int record, object value) { // just silently set the value
  1080. try {
  1081. Debug.Assert(null != value, "setting null, expecting dbnull");
  1082. Debug.Assert(null != this.table, "storage with no DataTable on column");
  1083. Debug.Assert(null != _storage, "no storage");
  1084. _storage.Set(record, value);
  1085. }
  1086. catch (Exception e) {
  1087. ExceptionBuilder.TraceExceptionForCapture(e);
  1088. throw ExceptionBuilder.SetFailed(value, this, DataType, e);
  1089. }
  1090. DataRow dr = GetDataRow(record);
  1091. if (dr != null) { // at initialization time (datatable.NewRow(), we would fill the storage with default value, but at that time we wont have datarow)
  1092. dr.LastChangedColumn = this;
  1093. }
  1094. }
  1095. internal void FreeRecord(int record) {
  1096. Debug.Assert(null != _storage, "no storage");
  1097. _storage.Set(record, _storage.NullValue);
  1098. }
  1099. /// <devdoc>
  1100. /// <para>
  1101. /// Gets or sets a value indicating whether the values in each row of the column must be unique.
  1102. /// </para>
  1103. /// </devdoc>
  1104. [
  1105. ResCategoryAttribute(Res.DataCategory_Data),
  1106. DefaultValue(false),
  1107. ResDescriptionAttribute(Res.DataColumnUniqueDescr),
  1108. DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
  1109. ]
  1110. public bool Unique {
  1111. get {
  1112. return unique;
  1113. }
  1114. set {
  1115. IntPtr hscp;
  1116. Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_Unique|API> %d#, %d{bool}\n", ObjectID, value);
  1117. try {
  1118. if (unique != value) {
  1119. if (value && expression != null) {
  1120. throw ExceptionBuilder.UniqueAndExpression();
  1121. }
  1122. UniqueConstraint oldConstraint = null;
  1123. if (table != null) {
  1124. if (value)
  1125. CheckUnique();
  1126. else {
  1127. for (System.Collections.IEnumerator e = Table.Constraints.GetEnumerator(); e.MoveNext(); ) {
  1128. UniqueConstraint o = (e.Current as UniqueConstraint);
  1129. if ((null != o) && (o.ColumnsReference.Length == 1) && (o.ColumnsReference[0] == this))
  1130. oldConstraint = o;
  1131. }
  1132. Debug.Assert(oldConstraint != null, "Should have found a column to remove from the collection.");
  1133. table.Constraints.CanRemove(oldConstraint, true);
  1134. }
  1135. }
  1136. this.unique = value;
  1137. if (table != null) {
  1138. if (value) {
  1139. // This should not fail due to a duplicate constraint. unique would have
  1140. // already been true if there was an existed UniqueConstraint for this column
  1141. UniqueConstraint constraint = new UniqueConstraint(this);
  1142. Debug.Assert(table.Constraints.FindKeyConstraint(this) == null, "Should not be a duplication constraint in collection");
  1143. table.Constraints.Add(constraint);
  1144. }
  1145. else
  1146. {
  1147. table.Constraints.Remove(oldConstraint);
  1148. //
  1149. }
  1150. }
  1151. }
  1152. }
  1153. finally {
  1154. Bid.ScopeLeave(ref hscp);
  1155. }
  1156. }
  1157. }
  1158. // FxCop Rule; getter not used! WebData 101301; so changing from Property to method
  1159. internal void InternalUnique(bool value) {
  1160. this.unique = value;
  1161. }
  1162. internal string XmlDataType {
  1163. get {
  1164. return dttype;
  1165. }
  1166. set {
  1167. dttype = value;
  1168. }
  1169. }
  1170. internal SimpleType SimpleType {
  1171. get {
  1172. return simpleType;
  1173. }
  1174. set {
  1175. simpleType = value;
  1176. // there is a change, since we are supporting hierarchy(bacause of Names Simple Type) old check (just one leel base check) is wrong
  1177. if (value != null && value.CanHaveMaxLength())
  1178. maxLength = simpleType.MaxLength;// this is temp solution, since we dont let simple content to have
  1179. //maxlength set but for simple type we want to set it, after coming to decision about it , we should
  1180. // use MaxLength property
  1181. }
  1182. }
  1183. /// <devdoc>
  1184. /// <para>Gets the <see cref='System.Data.MappingType'/> of the column.</para>
  1185. /// </devdoc>
  1186. [
  1187. DefaultValue(MappingType.Element),
  1188. ResDescriptionAttribute(Res.DataColumnMappingDescr)
  1189. ]
  1190. public virtual MappingType ColumnMapping {
  1191. get {
  1192. return columnMapping;
  1193. }
  1194. set {
  1195. Bid.Trace("<ds.DataColumn.set_ColumnMapping|API> %d#, %d{ds.MappingType}\n", ObjectID, (int)value);
  1196. if (value != columnMapping) {
  1197. if (value == MappingType.SimpleContent && table != null) {
  1198. int threshold = 0;
  1199. if (columnMapping == MappingType.Element)
  1200. threshold = 1;
  1201. if (this.dataType == typeof(Char))
  1202. throw ExceptionBuilder.CannotSetSimpleContent(ColumnName, this.dataType);
  1203. if (table.XmlText != null && table.XmlText != this)
  1204. throw ExceptionBuilder.CannotAddColumn3();
  1205. if (table.ElementColumnCount > threshold)
  1206. throw ExceptionBuilder.CannotAddColumn4(this.ColumnName);
  1207. }
  1208. RaisePropertyChanging("ColumnMapping");
  1209. if (table != null) {
  1210. if (columnMapping == MappingType.SimpleContent)
  1211. table.xmlText = null;
  1212. if (value == MappingType.Element)
  1213. table.ElementColumnCount++;
  1214. else if (columnMapping == MappingType.Element)
  1215. table.ElementColumnCount--;
  1216. }
  1217. columnMapping = value;
  1218. if (value == MappingType.SimpleContent) {
  1219. _columnUri = null;
  1220. if (table != null) {
  1221. table.XmlText = this;
  1222. }
  1223. this.SimpleType = null;
  1224. }
  1225. }
  1226. }
  1227. }
  1228. internal event PropertyChangedEventHandler PropertyChanging {
  1229. add {
  1230. onPropertyChangingDelegate += value;
  1231. }
  1232. remove {
  1233. onPropertyChangingDelegate -= value;
  1234. }
  1235. }
  1236. internal void CheckColumnConstraint(DataRow row, DataRowAction action) {
  1237. if (table.UpdatingCurrent(row, action)) {
  1238. CheckNullable(row);
  1239. CheckMaxLength(row);
  1240. }
  1241. }
  1242. internal bool CheckMaxLength() {
  1243. if ((0 <= maxLength) && (null != Table) && (0 < Table.Rows.Count)) {
  1244. Debug.Assert(IsStringType, "not a String or SqlString column");
  1245. foreach (DataRow dr in Table.Rows) {
  1246. if (dr.HasVersion(DataRowVersion.Current)) {
  1247. if (maxLength < GetStringLength(dr.GetCurrentRecordNo())) {
  1248. return false;
  1249. }
  1250. }
  1251. }
  1252. }
  1253. return true;
  1254. }
  1255. internal void CheckMaxLength(DataRow dr) {
  1256. if (0 <= maxLength) {
  1257. Debug.Assert(IsStringType, "not a String or SqlString column");
  1258. if (maxLength < GetStringLength(dr.GetDefaultRecord())) {
  1259. throw ExceptionBuilder.LongerThanMaxLength(this);
  1260. }
  1261. }
  1262. }
  1263. internal protected void CheckNotAllowNull() {
  1264. if (_storage == null)
  1265. return;
  1266. if (sortIndex != null) {
  1267. if (sortIndex.IsKeyInIndex(_storage.NullValue)) {// here we do use strong typed NULL for Sql types
  1268. throw ExceptionBuilder.NullKeyValues(ColumnName);
  1269. }
  1270. }
  1271. else { // since we do not have index, we so sequential search
  1272. foreach (DataRow dr in this.table.Rows) {
  1273. if (dr.RowState == DataRowState.Deleted)
  1274. continue;
  1275. if (!implementsINullable) {
  1276. if (dr[this] == DBNull.Value) {
  1277. throw ExceptionBuilder.NullKeyValues(ColumnName);
  1278. }
  1279. }
  1280. else {
  1281. if (DataStorage.IsObjectNull(dr[this])) {
  1282. throw ExceptionBuilder.NullKeyValues(ColumnName);
  1283. }
  1284. }
  1285. }
  1286. }
  1287. }
  1288. internal void CheckNullable(DataRow row) {
  1289. if (!AllowDBNull) {
  1290. Debug.Assert(null != _storage, "no storage");
  1291. if (_storage.IsNull(row.GetDefaultRecord())) {
  1292. throw ExceptionBuilder.NullValues(ColumnName);
  1293. }
  1294. }
  1295. }
  1296. protected void CheckUnique() {
  1297. if (!SortIndex.CheckUnique()) {
  1298. // Throws an exception and the name of any column if its Unique property set to
  1299. // True and non-unique values are found in the column.
  1300. throw ExceptionBuilder.NonUniqueValues(ColumnName);
  1301. }
  1302. }
  1303. internal int Compare(int record1, int record2) {
  1304. Debug.Assert(null != _storage, "null storage");
  1305. return _storage.Compare(record1, record2);
  1306. }
  1307. internal bool CompareValueTo(int record1, object value, bool checkType) {
  1308. // this method is used to make sure value and exact type match.
  1309. int valuesMatch = CompareValueTo(record1, value);
  1310. // if values match according to storage, do extra checks for exact compare
  1311. if (valuesMatch == 0) {
  1312. Type leftType = value.GetType();
  1313. Type rightType = _storage.Get(record1).GetType();
  1314. // if strings, then do exact character by character check
  1315. if (leftType == typeof(System.String) && rightType == typeof(System.String)) {
  1316. return String.CompareOrdinal((string)_storage.Get(record1), (string)value) == 0 ? true : false;
  1317. }
  1318. // make sure same type
  1319. else if (leftType == rightType) {
  1320. return true;
  1321. }
  1322. }
  1323. return false;
  1324. }
  1325. internal int CompareValueTo(int record1, object value) {
  1326. Debug.Assert(null != _storage, "null storage");
  1327. return _storage.CompareValueTo(record1, value);
  1328. }
  1329. internal object ConvertValue(object value) {
  1330. Debug.Assert(null != _storage, "null storage");
  1331. return _storage.ConvertValue(value);
  1332. }
  1333. internal void Copy(int srcRecordNo, int dstRecordNo) {
  1334. Debug.Assert(null != _storage, "null storage");
  1335. _storage.Copy(srcRecordNo, dstRecordNo);
  1336. }
  1337. // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set.
  1338. [MethodImpl(MethodImplOptions.NoInlining)]
  1339. internal DataColumn Clone() {
  1340. DataColumn clone = (DataColumn)Activator.CreateInstance(this.GetType());
  1341. // set All properties
  1342. // clone.columnMapping = columnMapping;
  1343. clone.SimpleType = SimpleType;
  1344. clone.allowNull = allowNull;
  1345. if (null != this.autoInc) {
  1346. clone.autoInc = this.autoInc.Clone();
  1347. }
  1348. clone.caption = caption;
  1349. clone.ColumnName = ColumnName;
  1350. clone._columnUri = _columnUri;
  1351. clone._columnPrefix = _columnPrefix;
  1352. clone.DataType = DataType;
  1353. clone.defaultValue = defaultValue;
  1354. clone.defaultValueIsNull = ((defaultValue == DBNull.Value) || (clone.ImplementsINullable && DataStorage.IsObjectSqlNull(defaultValue))) ? true : false;
  1355. clone.columnMapping = columnMapping;// clone column Mapping since we dont let MaxLength to be set throu API
  1356. //
  1357. clone.readOnly = readOnly;
  1358. clone.MaxLength = MaxLength;
  1359. clone.dttype = dttype;
  1360. clone._dateTimeMode = _dateTimeMode;
  1361. // so if we have set it, we should continue preserving the information
  1362. // ...Extended Properties
  1363. if (this.extendedProperties != null) {
  1364. foreach (Object key in this.extendedProperties.Keys) {
  1365. clone.ExtendedProperties[key] = this.extendedProperties[key];
  1366. }
  1367. }
  1368. return clone;
  1369. }
  1370. /// <devdoc>
  1371. /// <para>Finds a relation that this column is the sole child of or null.</para>
  1372. /// </devdoc>
  1373. internal DataRelation FindParentRelation() {
  1374. DataRelation[] parentRelations = new DataRelation[Table.ParentRelations.Count];
  1375. Table.ParentRelations.CopyTo(parentRelations, 0);
  1376. for (int i = 0; i < parentRelations.Length; i++) {
  1377. DataRelation relation = parentRelations[i];
  1378. DataKey key = relation.ChildKey;
  1379. if (key.ColumnsReference.Length == 1 && key.ColumnsReference[0] == this) {
  1380. return relation;
  1381. }
  1382. }
  1383. // should we throw an exception?
  1384. return null;
  1385. }
  1386. internal object GetAggregateValue(int[] records, AggregateType kind) {
  1387. if (_storage == null) {
  1388. if (kind == AggregateType.Count)
  1389. return 0;
  1390. else
  1391. return DBNull.Value;
  1392. }
  1393. return _storage.Aggregate(records, kind);
  1394. }
  1395. private int GetStringLength(int record) {
  1396. Debug.Assert(null != _storage, "no storage");
  1397. return _storage.GetStringLength(record);
  1398. }
  1399. internal void Init(int record) {
  1400. if (AutoIncrement) {
  1401. object value = this.autoInc.Current;
  1402. this.autoInc.MoveAfter();
  1403. Debug.Assert(null != _storage, "no storage");
  1404. _storage.Set(record, value);
  1405. }
  1406. else
  1407. this[record] = defaultValue;
  1408. }
  1409. internal static bool IsAutoIncrementType(Type dataType) {
  1410. return ((dataType == typeof(Int32)) || (dataType == typeof(Int64)) || (dataType == typeof(Int16)) || (dataType == typeof(Decimal)) || (dataType == typeof(System.Numerics.BigInteger)) ||
  1411. (dataType == typeof(SqlInt32)) || (dataType == typeof(SqlInt64)) || (dataType == typeof(SqlInt16)) || (dataType == typeof(SqlDecimal)));
  1412. }
  1413. private bool IsColumnMappingValid(StorageType typeCode, MappingType mapping) {
  1414. if ((mapping != MappingType.Element) && DataStorage.IsTypeCustomType(typeCode)) {
  1415. return false;
  1416. }
  1417. return true;
  1418. }
  1419. internal bool IsCustomType {
  1420. get {
  1421. if (null != _storage)
  1422. return _storage.IsCustomDefinedType;
  1423. return DataStorage.IsTypeCustomType(DataType);
  1424. }
  1425. }
  1426. internal bool IsValueCustomTypeInstance(object value) {
  1427. // if instance is not a storage supported type (built in or SQL types)
  1428. return (DataStorage.IsTypeCustomType(value.GetType()) && !(value is Type));
  1429. }
  1430. internal bool ImplementsIXMLSerializable {
  1431. get {
  1432. return implementsIXMLSerializable;
  1433. }
  1434. }
  1435. internal bool IsNull(int record) {
  1436. Debug.Assert(null != _storage, "no storage");
  1437. return _storage.IsNull(record);
  1438. }
  1439. /// <devdoc>
  1440. /// Returns true if this column is a part of a Parent or Child key for a relation.
  1441. /// </devdoc>
  1442. internal bool IsInRelation() {
  1443. DataKey key;
  1444. DataRelationCollection rels = table.ParentRelations;
  1445. Debug.Assert(rels != null, "Invalid ParentRelations");
  1446. for (int i = 0; i < rels.Count; i++) {
  1447. key = rels[i].ChildKey;
  1448. Debug.Assert(key.HasValue, "Invalid child key (null)");
  1449. if (key.ContainsColumn(this)) {
  1450. return true;
  1451. }
  1452. }
  1453. rels = table.ChildRelations;
  1454. Debug.Assert(rels != null, "Invalid ChildRelations");
  1455. for (int i = 0; i < rels.Count; i++) {
  1456. key = rels[i].ParentKey;
  1457. Debug.Assert(key.HasValue, "Invalid parent key (null)");
  1458. if (key.ContainsColumn(this)) {
  1459. return true;
  1460. }
  1461. }
  1462. return false;
  1463. }
  1464. internal bool IsMaxLengthViolated() {
  1465. if (MaxLength < 0)
  1466. return true;
  1467. bool error = false;
  1468. object value;
  1469. string errorText = null;
  1470. foreach (DataRow dr in Table.Rows) {
  1471. if (dr.HasVersion(DataRowVersion.Current)) {
  1472. value = dr[this];
  1473. if (!this.isSqlType) {
  1474. if (value != null && value != DBNull.Value && ((string)value).Length > MaxLength) {
  1475. if (errorText == null) {
  1476. errorText = ExceptionBuilder.MaxLengthViolationText(this.ColumnName);
  1477. }
  1478. dr.RowError = errorText;
  1479. dr.SetColumnError(this, errorText);
  1480. error = true;
  1481. }
  1482. }
  1483. else {
  1484. if (!DataStorage.IsObjectNull(value) && ((SqlString)value).Value.Length > MaxLength) {
  1485. if (errorText == null) {
  1486. errorText = ExceptionBuilder.MaxLengthViolationText(this.ColumnName);
  1487. }
  1488. dr.RowError = errorText;
  1489. dr.SetColumnError(this, errorText);
  1490. error = true;
  1491. }
  1492. }
  1493. }
  1494. }
  1495. return error;
  1496. }
  1497. internal bool IsNotAllowDBNullViolated() {//
  1498. Index index = this.SortIndex;
  1499. DataRow[] rows = index.GetRows(index.FindRecords(DBNull.Value));
  1500. for (int i = 0; i < rows.Length; i++) {
  1501. string errorText = ExceptionBuilder.NotAllowDBNullViolationText(this.ColumnName);
  1502. rows[i].RowError = errorText;
  1503. rows[i].SetColumnError(this, errorText);
  1504. }
  1505. return (rows.Length > 0);
  1506. }
  1507. internal void FinishInitInProgress() {
  1508. if (this.Computed)
  1509. BindExpression();
  1510. }
  1511. protected virtual void OnPropertyChanging(PropertyChangedEventArgs pcevent) {
  1512. if (onPropertyChangingDelegate != null)
  1513. onPropertyChangingDelegate(this, pcevent);
  1514. }
  1515. protected internal void RaisePropertyChanging(string name) {
  1516. OnPropertyChanging(new PropertyChangedEventArgs(name));
  1517. }
  1518. private void InsureStorage() {
  1519. if (_storage == null) {
  1520. _storage = DataStorage.CreateStorage(this, dataType, _storageType);
  1521. }
  1522. }
  1523. internal void SetCapacity(int capacity) {
  1524. InsureStorage();
  1525. _storage.SetCapacity(capacity);
  1526. }
  1527. private bool ShouldSerializeDefaultValue() {
  1528. return (!DefaultValueIsNull);
  1529. }
  1530. internal void OnSetDataSet() {
  1531. }
  1532. // Returns the <see cref='System.Data.DataColumn.Expression'/> of the column, if one exists.
  1533. public override string ToString() {
  1534. if (this.expression == null)
  1535. return this.ColumnName;
  1536. else
  1537. return this.ColumnName + " + " + this.Expression;
  1538. }
  1539. internal object ConvertXmlToObject(string s) {
  1540. Debug.Assert(s != null, "Caller is resposible for missing element/attribure case");
  1541. InsureStorage();
  1542. return _storage.ConvertXmlToObject(s);
  1543. }
  1544. internal object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute xmlAttrib) {
  1545. InsureStorage();
  1546. return _storage.ConvertXmlToObject(xmlReader, xmlAttrib);
  1547. }
  1548. internal string ConvertObjectToXml(object value) {
  1549. Debug.Assert(value != null && (value != DBNull.Value), "Caller is resposible for checking on DBNull");
  1550. InsureStorage();
  1551. return _storage.ConvertObjectToXml(value);
  1552. }
  1553. internal void ConvertObjectToXml(object value, XmlWriter xmlWriter, XmlRootAttribute xmlAttrib) {
  1554. Debug.Assert(value != null && (value != DBNull.Value), "Caller is resposible for checking on DBNull");
  1555. InsureStorage();
  1556. _storage.ConvertObjectToXml(value, xmlWriter, xmlAttrib);
  1557. }
  1558. internal object GetEmptyColumnStore(int recordCount) {
  1559. InsureStorage();
  1560. return _storage.GetEmptyStorageInternal(recordCount);
  1561. }
  1562. internal void CopyValueIntoStore(int record, object store, BitArray nullbits, int storeIndex) {
  1563. Debug.Assert(null != _storage, "no storage");
  1564. _storage.CopyValueInternal(record, store, nullbits, storeIndex);
  1565. }
  1566. internal void SetStorage(object store, BitArray nullbits) {
  1567. InsureStorage();
  1568. _storage.SetStorageInternal(store, nullbits);
  1569. }
  1570. internal void AddDependentColumn(DataColumn expressionColumn) {
  1571. if (dependentColumns == null) {
  1572. dependentColumns = new List<DataColumn>();
  1573. }
  1574. Debug.Assert(!dependentColumns.Contains(expressionColumn), "duplicate column - expected to be unique");
  1575. dependentColumns.Add(expressionColumn);
  1576. this.table.AddDependentColumn(expressionColumn);
  1577. }
  1578. internal void RemoveDependentColumn(DataColumn expressionColumn) {
  1579. if (dependentColumns != null && dependentColumns.Contains(expressionColumn)) {
  1580. dependentColumns.Remove(expressionColumn);
  1581. }
  1582. this.table.RemoveDependentColumn(expressionColumn);
  1583. }
  1584. internal void HandleDependentColumnList(DataExpression oldExpression, DataExpression newExpression) {
  1585. DataColumn[] dependency;
  1586. // remove this column from the dependentColumn list of the columns this column depends on.
  1587. if (oldExpression != null) {
  1588. dependency = oldExpression.GetDependency();
  1589. foreach (DataColumn col in dependency) {
  1590. Debug.Assert(null != col, "null datacolumn in expression dependencies");
  1591. col.RemoveDependentColumn(this);
  1592. if (col.table != this.table) {
  1593. this.table.RemoveDependentColumn(this);
  1594. }
  1595. }
  1596. this.table.RemoveDependentColumn(this);
  1597. }
  1598. if (newExpression != null) {
  1599. // get the list of columns that this expression depends on
  1600. dependency = newExpression.GetDependency();
  1601. // add this column to dependent column list of each column this column depends on
  1602. foreach (DataColumn col in dependency) {
  1603. col.AddDependentColumn(this);
  1604. if (col.table != this.table) {
  1605. this.table.AddDependentColumn(this);
  1606. }
  1607. }
  1608. this.table.AddDependentColumn(this);
  1609. }
  1610. }
  1611. }
  1612. internal abstract class AutoIncrementValue {
  1613. private bool auto;
  1614. internal bool Auto {
  1615. get { return this.auto; }
  1616. set { this.auto = value; }
  1617. }
  1618. internal abstract object Current { get; set; }
  1619. internal abstract long Seed { get; set; }
  1620. internal abstract long Step { get; set; }
  1621. internal abstract Type DataType { get; }
  1622. internal abstract void SetCurrent(object value, IFormatProvider formatProvider);
  1623. internal abstract void SetCurrentAndIncrement(object value);
  1624. internal abstract void MoveAfter();
  1625. internal AutoIncrementValue Clone() {
  1626. AutoIncrementValue clone = (this is AutoIncrementInt64) ? (AutoIncrementValue)new AutoIncrementInt64() : (AutoIncrementValue)new AutoIncrementBigInteger();
  1627. clone.Auto = this.Auto;
  1628. clone.Seed = this.Seed;
  1629. clone.Step = this.Step;
  1630. clone.Current = this.Current;
  1631. return clone;
  1632. }
  1633. }
  1634. /// <summary>the auto stepped value with Int64 representation</summary>
  1635. /// <remarks>use unchecked behavior for Dev10 Bug 568510</remarks>
  1636. internal sealed class AutoIncrementInt64 : AutoIncrementValue {
  1637. /// <summary>the last returned auto incremented value</summary>
  1638. private System.Int64 current;
  1639. /// <summary>the initial value use to set current</summary>
  1640. private System.Int64 seed;
  1641. /// <summary>the value by which to offset the next value</summary>
  1642. private System.Int64 step = 1;
  1643. /// <summary>Gets and sets the current auto incremented value to use</summary>
  1644. internal override object Current {
  1645. get { return this.current; }
  1646. set { this.current = (Int64)value; }
  1647. }
  1648. internal override Type DataType { get { return typeof(System.Int64); } }
  1649. /// <summary>Get and sets the initial seed value.</summary>
  1650. internal override long Seed {
  1651. get { return this.seed; }
  1652. set {
  1653. if ((this.current == this.seed) || this.BoundaryCheck(value)) {
  1654. this.current = value;
  1655. }
  1656. this.seed = value;
  1657. }
  1658. }
  1659. /// <summary>Get and sets the stepping value.</summary>
  1660. /// <exception cref="ArugmentException">if value is 0</exception>
  1661. internal override long Step {
  1662. get { return this.step; }
  1663. set {
  1664. if (0 == value) {
  1665. throw ExceptionBuilder.AutoIncrementSeed();
  1666. }
  1667. if (this.step != value) {
  1668. if (this.current != this.Seed) {
  1669. this.current = unchecked(this.current - this.step + value);
  1670. }
  1671. this.step = value;
  1672. }
  1673. }
  1674. }
  1675. internal override void MoveAfter() {
  1676. this.current = unchecked(this.current + this.step);
  1677. }
  1678. internal override void SetCurrent(object value, IFormatProvider formatProvider) {
  1679. this.current = Convert.ToInt64(value, formatProvider);
  1680. }
  1681. internal override void SetCurrentAndIncrement(object value) {
  1682. Debug.Assert(null != value && DataColumn.IsAutoIncrementType(value.GetType()) && !(value is System.Numerics.BigInteger), "unexpected value for autoincrement");
  1683. System.Int64 v = (Int64)SqlConvert.ChangeType2(value, StorageType.Int64, typeof(Int64), CultureInfo.InvariantCulture);
  1684. if (this.BoundaryCheck(v)) {
  1685. this.current = unchecked(v + this.step);
  1686. }
  1687. }
  1688. private bool BoundaryCheck(System.Numerics.BigInteger value) {
  1689. return (((this.step < 0) && (value <= this.current)) || ((0 < this.step) && (this.current <= value)));
  1690. }
  1691. }
  1692. /// <summary>the auto stepped value with BigInteger representation</summary>
  1693. internal sealed class AutoIncrementBigInteger : AutoIncrementValue {
  1694. /// <summary>the current auto incremented value to use</summary>
  1695. private System.Numerics.BigInteger current;
  1696. /// <summary>the initial value use to set current</summary>
  1697. private System.Int64 seed;
  1698. /// <summary>the value by which to offset the next value</summary>
  1699. private System.Numerics.BigInteger step = 1;
  1700. /// <summary>Gets and sets the current auto incremented value to use</summary>
  1701. internal override object Current {
  1702. get { return this.current; }
  1703. set { this.current = (System.Numerics.BigInteger)value; }
  1704. }
  1705. internal override Type DataType { get { return typeof(System.Numerics.BigInteger); } }
  1706. /// <summary>Get and sets the initial seed value.</summary>
  1707. internal override long Seed {
  1708. get { return this.seed; }
  1709. set {
  1710. if ((this.current == this.seed) || this.BoundaryCheck(value)) {
  1711. this.current = value;
  1712. }
  1713. this.seed = value;
  1714. }
  1715. }
  1716. /// <summary>Get and sets the stepping value.</summary>
  1717. /// <exception cref="ArugmentException">if value is 0</exception>
  1718. internal override long Step {
  1719. get { return (long)this.step; }
  1720. set {
  1721. if (0 == value) {
  1722. throw ExceptionBuilder.AutoIncrementSeed();
  1723. }
  1724. if (this.step != value) {
  1725. if (this.current != this.Seed) {
  1726. this.current = checked(this.current - this.step + value);
  1727. }
  1728. this.step = value;
  1729. }
  1730. }
  1731. }
  1732. internal override void MoveAfter() {
  1733. this.current = checked(this.current + this.step);
  1734. }
  1735. internal override void SetCurrent(object value, IFormatProvider formatProvider) {
  1736. this.current = BigIntegerStorage.ConvertToBigInteger(value, formatProvider);
  1737. }
  1738. internal override void SetCurrentAndIncrement(object value) {
  1739. System.Numerics.BigInteger v = (System.Numerics.BigInteger)value;
  1740. if (this.BoundaryCheck(v)) {
  1741. this.current = v + this.step;
  1742. }
  1743. }
  1744. private bool BoundaryCheck(System.Numerics.BigInteger value) {
  1745. return (((this.step < 0) && (value <= this.current)) || ((0 < this.step) && (this.current <= value)));
  1746. }
  1747. }
  1748. }