| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959 |
- //------------------------------------------------------------------------------
- // <copyright file="DataColumn.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- //------------------------------------------------------------------------------
- namespace System.Data {
- using System;
- using System.Xml;
- using System.Data.Common;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Collections;
- using System.Globalization;
- using System.Data.SqlTypes;
- using System.Xml.Serialization;
- using System.Collections.Generic;
- using System.Runtime.CompilerServices;
- /// <devdoc>
- /// <para>
- /// Represents one column of data in a <see cref='System.Data.DataTable'/>.
- /// </para>
- /// </devdoc>
- [
- ToolboxItem(false),
- DesignTimeVisible(false),
- DefaultProperty("ColumnName"),
- Editor("Microsoft.VSDesigner.Data.Design.DataColumnEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
- ]
- public class DataColumn : MarshalByValueComponent {
- // properties
- private bool allowNull = true;
- private string caption = null;
- private string _columnName = null;
- private Type dataType = null;
- private StorageType _storageType;
- internal object defaultValue = DBNull.Value; // DefaultValue Converter
- private DataSetDateTime _dateTimeMode = DataSetDateTime.UnspecifiedLocal;
- private DataExpression expression = null;
- private int maxLength = -1;
- private int _ordinal = -1;
- private bool readOnly = false;
- internal Index sortIndex = null;
- internal DataTable table = null;
- private bool unique = false;
- internal MappingType columnMapping = MappingType.Element;
- internal int _hashCode;
- internal int errors;
- private bool isSqlType = false;
- private bool implementsINullable = false;
- private bool implementsIChangeTracking = false;
- private bool implementsIRevertibleChangeTracking = false;
- private bool implementsIXMLSerializable = false;
- private bool defaultValueIsNull = true;
- // list of columns whose expression consume values from this column
- internal List<DataColumn> dependentColumns = null;
- // collections
- internal PropertyCollection extendedProperties = null;
- // events
- private PropertyChangedEventHandler onPropertyChangingDelegate = null;
- // state
- private DataStorage _storage;
- /// <summary>represents current value to return, usage pattern is .get_Current then MoveAfter</summary>
- private AutoIncrementValue autoInc;
- //
- // The _columnClass member is the class for the unfoliated virtual nodes in the XML.
- //
- internal string _columnUri = null;
- private string _columnPrefix = "";
- internal string encodedColumnName = null;
- //
- internal string dttype = ""; // The type specified in dt:type attribute
- internal SimpleType simpleType = null;
- private static int _objectTypeCount; // Bid counter
- private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
- /// <devdoc>
- /// <para>
- /// Initializes a new instance of a <see cref='System.Data.DataColumn'/>
- /// class.
- /// </para>
- /// </devdoc>
- public DataColumn() : this(null, typeof(string), null, MappingType.Element) {
- }
- /// <devdoc>
- /// <para>
- /// Inititalizes a new instance of the <see cref='System.Data.DataColumn'/> class
- /// using the specified column name.
- /// </para>
- /// </devdoc>
- public DataColumn(string columnName) : this(columnName, typeof(string), null, MappingType.Element) {
- }
- /// <devdoc>
- /// <para>
- /// Inititalizes a new instance of the <see cref='System.Data.DataColumn'/> class
- /// using the specified column name and data type.
- /// </para>
- /// </devdoc>
- public DataColumn(string columnName, Type dataType) : this(columnName, dataType, null, MappingType.Element) {
- }
- /// <devdoc>
- /// <para>
- /// Initializes a new instance
- /// of the <see cref='System.Data.DataColumn'/> class
- /// using the specified name, data type, and expression.
- /// </para>
- /// </devdoc>
- public DataColumn(string columnName, Type dataType, string expr) : this(columnName, dataType, expr, MappingType.Element) {
- }
- /// <devdoc>
- /// <para>
- /// Initializes a new instance of the <see cref='System.Data.DataColumn'/> class
- /// using
- /// the specified name, data type, expression, and value that determines whether the
- /// column is an attribute.
- /// </para>
- /// </devdoc>
- public DataColumn(string columnName, Type dataType, string expr, MappingType type) {
- GC.SuppressFinalize(this);
- Bid.Trace("<ds.DataColumn.DataColumn|API> %d#, columnName='%ls', expr='%ls', type=%d{ds.MappingType}\n",
- ObjectID, columnName, expr, (int)type);
- if (dataType == null) {
- throw ExceptionBuilder.ArgumentNull("dataType");
- }
- StorageType typeCode = DataStorage.GetStorageType(dataType);
- if (DataStorage.ImplementsINullableValue(typeCode, dataType)) {
- throw ExceptionBuilder.ColumnTypeNotSupported();
- }
- _columnName = columnName ?? string.Empty;
- SimpleType stype = SimpleType.CreateSimpleType(typeCode, dataType);
- if (null != stype) {
- this.SimpleType = stype;
- }
- UpdateColumnType(dataType, typeCode);
- if ((null != expr) && (0 < expr.Length)) {
- // @perfnote: its a performance hit to set Expression to the empty str when we know it will come out null
- this.Expression = expr;
- }
- this.columnMapping = type;
- }
- private void UpdateColumnType(Type type, StorageType typeCode) {
- dataType = type;
- _storageType = typeCode;
- if (StorageType.DateTime != typeCode) { // revert _dateTimeMode back to default, when column type is changed
- _dateTimeMode = DataSetDateTime.UnspecifiedLocal;
- }
- DataStorage.ImplementsInterfaces(
- typeCode, type,
- out isSqlType,
- out implementsINullable,
- out implementsIXMLSerializable,
- out implementsIChangeTracking,
- out implementsIRevertibleChangeTracking);
- if (!isSqlType && implementsINullable) {
- SqlUdtStorage.GetStaticNullForUdtType(type);
- }
- }
- // PUBLIC PROPERTIES
- /// <devdoc>
- /// <para>
- /// Gets or sets a value indicating whether null
- /// values are
- /// allowed in this column for rows belonging to the table.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue(true),
- ResDescriptionAttribute(Res.DataColumnAllowNullDescr)
- ]
- public bool AllowDBNull {
- get {
- return allowNull;
- }
- set {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_AllowDBNull|API> %d#, %d{bool}\n", ObjectID, value);
- try {
- if (allowNull != value) {
- if (table != null) {
- if (!value && table.EnforceConstraints)
- CheckNotAllowNull();
- }
- this.allowNull = value;
- }
- //
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets or
- /// sets a value indicating whether the column automatically increments the value of the column for new
- /// rows added to the table.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- RefreshProperties(RefreshProperties.All),
- DefaultValue(false),
- ResDescriptionAttribute(Res.DataColumnAutoIncrementDescr)
- ]
- public bool AutoIncrement {
- get {
- return ((null != autoInc) && (autoInc.Auto));
- }
- set {
- Bid.Trace("<ds.DataColumn.set_AutoIncrement|API> %d#, %d{bool}\n", ObjectID, value);
- if (this.AutoIncrement != value) {
- if (value) {
- if (expression != null) {
- throw ExceptionBuilder.AutoIncrementAndExpression();
- }
- // if (defaultValue != null && defaultValue != DBNull.Value) {
- if (!DefaultValueIsNull) {
- throw ExceptionBuilder.AutoIncrementAndDefaultValue();
- }
- if (!IsAutoIncrementType(DataType)) {
- if (HasData) {
- throw ExceptionBuilder.AutoIncrementCannotSetIfHasData(DataType.Name);
- }
- DataType = typeof(int);
- }
- }
- this.AutoInc.Auto = value;
- }
- }
- }
- internal object AutoIncrementCurrent {
- get { return ((null != this.autoInc) ? this.autoInc.Current : this.AutoIncrementSeed); }
- set {
- if ((System.Numerics.BigInteger)this.AutoIncrementSeed != BigIntegerStorage.ConvertToBigInteger(value, this.FormatProvider)) {
- this.AutoInc.SetCurrent(value, this.FormatProvider);
- }
- }
- }
- internal AutoIncrementValue AutoInc {
- get {
- return (this.autoInc ?? (this.autoInc = ((this.DataType == typeof(System.Numerics.BigInteger))
- ? (AutoIncrementValue)new AutoIncrementBigInteger()
- : new AutoIncrementInt64())));
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets
- /// or sets the starting value for a column that has its
- /// <see cref='System.Data.DataColumn.AutoIncrement'/> property
- /// set to <see langword='true'/>
- /// .
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue((Int64)0),
- ResDescriptionAttribute(Res.DataColumnAutoIncrementSeedDescr)
- ]
- public Int64 AutoIncrementSeed {
- get {
- return ((null != this.autoInc) ? this.autoInc.Seed : 0L);
- }
- set {
- Bid.Trace("<ds.DataColumn.set_AutoIncrementSeed|API> %d#, %I64d\n", ObjectID, value);
- if (this.AutoIncrementSeed != value) {
- this.AutoInc.Seed = value;
- }
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets or sets the increment used by a column with its <see cref='System.Data.DataColumn.AutoIncrement'/>
- /// property set to <see langword='true'/>
- /// .
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue((Int64)1),
- ResDescriptionAttribute(Res.DataColumnAutoIncrementStepDescr)
- ]
- public Int64 AutoIncrementStep {
- get {
- return ((null != this.autoInc) ? this.autoInc.Step : 1L);
- }
- set {
- Bid.Trace("<ds.DataColumn.set_AutoIncrementStep|API> %d#, %I64d\n", ObjectID, value);
- if (this.AutoIncrementStep != value) {
- this.AutoInc.Step = value;
- }
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets or sets
- /// the caption for this column.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataColumnCaptionDescr)
- ]
- public string Caption {
- get {
- return (caption != null) ? caption : _columnName;
- }
- set {
- if (value == null)
- value = "";
- if (caption == null || String.Compare(caption, value, true, Locale) != 0) {
- caption = value;
- }
- }
- }
- /// <devdoc>
- /// <para>
- /// Resets the <see cref='System.Data.DataColumn.Caption'/> property to its previous value, or
- /// to <see langword='null'/> .
- /// </para>
- /// </devdoc>
- private void ResetCaption() {
- if (caption != null) {
- caption = null;
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets a value indicating whether the <see cref='System.Data.DataColumn.Caption'/> has been explicitly set.
- /// </para>
- /// </devdoc>
- private bool ShouldSerializeCaption() {
- return (caption != null);
- }
- /// <devdoc>
- /// <para>
- /// Gets or sets the name of the column within the <see cref='System.Data.DataColumnCollection'/>.
- /// </para>
- /// </devdoc>
- [
- RefreshProperties(RefreshProperties.All),
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue(""),
- ResDescriptionAttribute(Res.DataColumnColumnNameDescr)
- ]
- public string ColumnName {
- get {
- return _columnName;
- }
- set {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_ColumnName|API> %d#, '%ls'\n", ObjectID, value);
- try {
- if (value == null) {
- value = "";
- }
- if (String.Compare(_columnName, value, true, Locale) != 0) {
- if (table != null) {
- if (value.Length == 0)
- throw ExceptionBuilder.ColumnNameRequired();
- table.Columns.RegisterColumnName(value, this);
- if (_columnName.Length != 0)
- table.Columns.UnregisterName(_columnName);
- }
- RaisePropertyChanging("ColumnName");
- _columnName = value;
- encodedColumnName = null;
- if (table != null) {
- table.Columns.OnColumnPropertyChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this));
- }
- }
- else if (_columnName != value) {
- RaisePropertyChanging("ColumnName");
- _columnName = value;
- encodedColumnName = null;
- if (table != null) {
- table.Columns.OnColumnPropertyChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this));
- }
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- internal string EncodedColumnName {
- get {
- if (this.encodedColumnName == null) {
- this.encodedColumnName = XmlConvert.EncodeLocalName(this.ColumnName);
- }
- Debug.Assert(this.encodedColumnName != null && this.encodedColumnName.Length != 0);
- return this.encodedColumnName;
- }
- }
- internal IFormatProvider FormatProvider {
- get {
- // used for formating/parsing not comparing
- return ((null != table) ? table.FormatProvider : CultureInfo.CurrentCulture);
- }
- }
- internal CultureInfo Locale {
- get {
- // used for comparing not formating/parsing
- return ((null != table) ? table.Locale : CultureInfo.CurrentCulture);
- }
- }
- internal int ObjectID {
- get {
- return _objectID;
- }
- }
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue(""),
- ResDescriptionAttribute(Res.DataColumnPrefixDescr)
- ]
- public string Prefix {
- get { return _columnPrefix; }
- set {
- if (value == null)
- value = "";
- Bid.Trace("<ds.DataColumn.set_Prefix|API> %d#, '%ls'\n", ObjectID, value);
- if ((XmlConvert.DecodeName(value) == value) && (XmlConvert.EncodeName(value) != value))
- throw ExceptionBuilder.InvalidPrefix(value);
- _columnPrefix = value;
- }
- }
- // Return the field value as a string. If the field value is NULL, then NULL is return.
- // If the column type is string and it's value is empty, then the empty string is returned.
- // 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
- // This method does not throw any formatting exceptions, since we can always format the field value to a string.
- internal string GetColumnValueAsString(DataRow row, DataRowVersion version) {
- object objValue = this[row.GetRecordFromVersion(version)];
- if (DataStorage.IsObjectNull(objValue)) {
- return null;
- }
- string value = ConvertObjectToXml(objValue);
- Debug.Assert(value != null);
- return value;
- }
- /// <devdoc>
- /// Whether this column computes values.
- /// </devdoc>
- internal bool Computed {
- get {
- return this.expression != null;
- }
- }
- /// <devdoc>
- /// The internal expression object that computes the values.
- /// </devdoc>
- internal DataExpression DataExpression {
- get {
- return this.expression;
- }
- }
- /// <devdoc>
- /// <para>
- /// The type
- /// of data stored in thecolumn.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue(typeof(string)),
- RefreshProperties(RefreshProperties.All),
- TypeConverter(typeof(ColumnTypeConverter)),
- ResDescriptionAttribute(Res.DataColumnDataTypeDescr)
- ]
- public Type DataType {
- get {
- return dataType;
- }
- set {
- if (dataType != value) {
- if (HasData) {
- throw ExceptionBuilder.CantChangeDataType();
- }
- if (value == null) {
- throw ExceptionBuilder.NullDataType();
- }
- StorageType typeCode = DataStorage.GetStorageType(value);
- if (DataStorage.ImplementsINullableValue(typeCode, value)) {
- throw ExceptionBuilder.ColumnTypeNotSupported();
- }
- if (table != null && IsInRelation()) {
- throw ExceptionBuilder.ColumnsTypeMismatch();
- }
- if (typeCode == StorageType.BigInteger && this.expression != null)
- {
- throw ExprException.UnsupportedDataType(value);
- }
- // If the DefualtValue is different from the Column DataType, we will coerce the value to the DataType
- if (!DefaultValueIsNull) {
- try {
- if (this.defaultValue is System.Numerics.BigInteger) {
- this.defaultValue = BigIntegerStorage.ConvertFromBigInteger((System.Numerics.BigInteger)this.defaultValue, value, this.FormatProvider);
- }
- else if (typeof(System.Numerics.BigInteger) == value) {
- this.defaultValue = BigIntegerStorage.ConvertToBigInteger(this.defaultValue, this.FormatProvider);
- }
- else if (typeof(string) == value) { // since string types can be null in value! DO NOT REMOVE THIS
- defaultValue = DefaultValue.ToString();
- }
- else if (typeof(SqlString) == value) { // since string types can be null in value! DO NOT REMOVE THIS
- defaultValue = SqlConvert.ConvertToSqlString(DefaultValue);
- }
- else if (typeof(object) != value) {
- DefaultValue = SqlConvert.ChangeTypeForDefaultValue(DefaultValue, value, FormatProvider);
- }
- }
- catch (InvalidCastException ex) {
- throw ExceptionBuilder.DefaultValueDataType(ColumnName, DefaultValue.GetType(), value, ex);
- }
- catch (FormatException ex) {
- throw ExceptionBuilder.DefaultValueDataType(ColumnName, DefaultValue.GetType(), value, ex);
- }
- }
- if (this.ColumnMapping == MappingType.SimpleContent)
- if (value == typeof(Char))
- throw ExceptionBuilder.CannotSetSimpleContentType(ColumnName, value);
- SimpleType = SimpleType.CreateSimpleType(typeCode, value);
- if (StorageType.String == typeCode) {
- maxLength = -1;
- }
- UpdateColumnType(value, typeCode);
- XmlDataType = null;
- if (AutoIncrement) {
- if (!IsAutoIncrementType(value)) {
- AutoIncrement = false;
- }
- if (null != this.autoInc) {
- // if you already have data you can't change the data type
- // if you don't have data - you wouldn't have incremented AutoIncrementCurrent.
- AutoIncrementValue inc = this.autoInc;
- this.autoInc = null;
- this.AutoInc.Auto = inc.Auto; // recreate with correct datatype
- this.AutoInc.Seed = inc.Seed;
- this.AutoInc.Step = inc.Step;
- if (this.autoInc.DataType == inc.DataType) {
- this.autoInc.Current = inc.Current;
- }
- else if (inc.DataType == typeof(Int64)) {
- this.AutoInc.Current = (System.Numerics.BigInteger)(long)inc.Current;
- }
- else {
- this.AutoInc.Current = checked((long)(System.Numerics.BigInteger)inc.Current);
- }
- }
- }
- }
- }
- }
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue(DataSetDateTime.UnspecifiedLocal),
- RefreshProperties(RefreshProperties.All),
- ResDescriptionAttribute(Res.DataColumnDateTimeModeDescr)
- ]
- public DataSetDateTime DateTimeMode {
- get {
- return _dateTimeMode;
- }
- set {
- if (_dateTimeMode != value) {
- 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].
- throw ExceptionBuilder.CannotSetDateTimeModeForNonDateTimeColumns();
- }
- switch (value) {
- case DataSetDateTime.Utc:
- case DataSetDateTime.Local:
- if (HasData) {
- throw ExceptionBuilder.CantChangeDateTimeMode(_dateTimeMode, value);
- }
- break;
- case DataSetDateTime.Unspecified:
- case DataSetDateTime.UnspecifiedLocal:
- if (_dateTimeMode == DataSetDateTime.Unspecified || _dateTimeMode == DataSetDateTime.UnspecifiedLocal) {
- break;
- }
- if (HasData) {
- throw ExceptionBuilder.CantChangeDateTimeMode(_dateTimeMode, value);
- }
- break;
- default:
- throw ExceptionBuilder.InvalidDateTimeMode(value);
- }
- _dateTimeMode = value;
- }
- }
- }
- /// <devdoc>
- /// <para>Gets or sets the default value for the
- /// column when creating new rows.</para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataColumnDefaultValueDescr),
- TypeConverter(typeof(DefaultValueTypeConverter))
- ]
- public object DefaultValue {
- get {
- Debug.Assert(defaultValue != null, "It should not have been set to null.");
- if (defaultValue == DBNull.Value && this.implementsINullable) { // for perf I dont access property
- if (_storage != null)
- defaultValue = _storage.NullValue;
- else if (this.isSqlType)
- defaultValue = SqlConvert.ChangeTypeForDefaultValue(defaultValue, this.dataType, FormatProvider);
- else if (this.implementsINullable) {
- System.Reflection.PropertyInfo propInfo = this.dataType.GetProperty("Null", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
- if (propInfo != null)
- defaultValue = propInfo.GetValue(null, null);
- }
- }
- return defaultValue;
- }
- set {
- Bid.Trace("<ds.DataColumn.set_DefaultValue|API> %d#\n", ObjectID);
- if (defaultValue == null || !DefaultValue.Equals(value)) {
- if (AutoIncrement) {
- throw ExceptionBuilder.DefaultValueAndAutoIncrement();
- }
- object newDefaultValue = (value == null) ? DBNull.Value : value;
- if (newDefaultValue != DBNull.Value && DataType != typeof(Object)) {
- // If the DefualtValue is different from the Column DataType, we will coerce the value to the DataType
- try {
- newDefaultValue = SqlConvert.ChangeTypeForDefaultValue(newDefaultValue, DataType, FormatProvider);
- }
- catch (InvalidCastException ex) {
- throw ExceptionBuilder.DefaultValueColumnDataType(ColumnName, newDefaultValue.GetType(), DataType, ex);
- }
- }
- defaultValue = newDefaultValue;
- // SQL BU Defect Tracking 401640: should not assign any value until conversion is successful.
- defaultValueIsNull = ((newDefaultValue == DBNull.Value) || (this.ImplementsINullable && DataStorage.IsObjectSqlNull(newDefaultValue))) ? true : false;
- }
- }
- }
- internal bool DefaultValueIsNull {
- get {
- return defaultValueIsNull;
- }
- }
- internal void BindExpression() {
- this.DataExpression.Bind(this.table);
- }
- /// <devdoc>
- /// <para>Gets
- /// or sets the expresssion used to either filter rows, calculate the column's
- /// value, or create an aggregate column.</para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- RefreshProperties(RefreshProperties.All),
- DefaultValue(""),
- ResDescriptionAttribute(Res.DataColumnExpressionDescr)
- ]
- public string Expression {
- get {
- return (this.expression == null ? "" : this.expression.Expression);
- }
- set {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_Expression|API> %d#, '%ls'\n", ObjectID, value);
- if (value == null) {
- value = "";
- }
- try {
- DataExpression newExpression = null;
- if (value.Length > 0) {
- DataExpression testExpression = new DataExpression(this.table, value, this.dataType);
- if (testExpression.HasValue) {
- newExpression = testExpression;
- }
- }
- if (expression == null && newExpression != null) {
- if (AutoIncrement || Unique) {
- throw ExceptionBuilder.ExpressionAndUnique();
- }
- // We need to make sure the column is not involved in any Constriants
- if (table != null) {
- for (int i = 0; i < table.Constraints.Count; i++) {
- if (table.Constraints[i].ContainsColumn(this)) {
- throw ExceptionBuilder.ExpressionAndConstraint(this, table.Constraints[i]);
- }
- }
- }
- bool oldReadOnly = ReadOnly;
- try {
- ReadOnly = true;
- }
- catch (ReadOnlyException e) {
- ExceptionBuilder.TraceExceptionForCapture(e);
- ReadOnly = oldReadOnly;
- throw ExceptionBuilder.ExpressionAndReadOnly();
- }
- }
- // re-calculate the evaluation queue
- if (this.table != null) {
- if (newExpression != null && newExpression.DependsOn(this)) {
- throw ExceptionBuilder.ExpressionCircular();
- }
- HandleDependentColumnList(expression, newExpression);
- //hold onto oldExpression in case of error applying new Expression.
- DataExpression oldExpression = this.expression;
- this.expression = newExpression;
- // because the column is attached to a table we need to re-calc values
- try {
- if (newExpression == null) {
- for (int i = 0; i < table.RecordCapacity; i++) {
- InitializeRecord(i);
- }
- }
- else {
- this.table.EvaluateExpressions(this);
- }
- // SQLBU 501916: DataTable internal index is corrupted:'5'
- this.table.ResetInternalIndexes(this);
- this.table.EvaluateDependentExpressions(this);
- }
- catch (Exception e1) {
- //
- if (!ADP.IsCatchableExceptionType(e1)) {
- throw;
- }
- ExceptionBuilder.TraceExceptionForCapture(e1);
- try {
- // in the case of error we need to set the column expression to the old value
- this.expression = oldExpression;
- HandleDependentColumnList(newExpression, expression);
- if (oldExpression == null) {
- for (int i = 0; i < table.RecordCapacity; i++) {
- InitializeRecord(i);
- }
- }
- else {
- this.table.EvaluateExpressions(this);
- }
- this.table.ResetInternalIndexes(this);
- this.table.EvaluateDependentExpressions(this);
- }
- catch (Exception e2) {
- //
- if (!ADP.IsCatchableExceptionType(e2)) {
- throw;
- }
- ExceptionBuilder.TraceExceptionWithoutRethrow(e2);
- }
- throw;
- }
- }
- else {
- //if column is not attached to a table, just set.
- this.expression = newExpression;
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- /// <devdoc>
- /// <para>Gets the collection of custom user information.</para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- Browsable(false),
- ResDescriptionAttribute(Res.ExtendedPropertiesDescr)
- ]
- public PropertyCollection ExtendedProperties {
- get {
- if (extendedProperties == null) {
- extendedProperties = new PropertyCollection();
- }
- return extendedProperties;
- }
- }
- /// <devdoc>
- /// Indicates whether this column is now storing data.
- /// </devdoc>
- internal bool HasData {
- get {
- return (_storage != null);
- }
- }
- internal bool ImplementsINullable {
- get {
- return implementsINullable;
- }
- }
- internal bool ImplementsIChangeTracking {
- get {
- return implementsIChangeTracking;
- }
- }
- internal bool ImplementsIRevertibleChangeTracking {
- get {
- return implementsIRevertibleChangeTracking;
- }
- }
- internal bool IsCloneable {
- get {
- Debug.Assert(null != _storage, "no storage");
- return _storage.IsCloneable;
- }
- }
- internal bool IsStringType {
- get {
- Debug.Assert(null != _storage, "no storage");
- return _storage.IsStringType;
- }
- }
- internal bool IsValueType {
- get {
- Debug.Assert(null != _storage, "no storage");
- return _storage.IsValueType;
- }
- }
- internal bool IsSqlType {
- get {
- return isSqlType;
- }
- }
- private void SetMaxLengthSimpleType() {
- if (this.simpleType != null) {
- Debug.Assert(this.simpleType.CanHaveMaxLength(), "expected simpleType to be string");
- this.simpleType.MaxLength = maxLength;
- // check if we reset the simpleType back to plain string
- if (this.simpleType.IsPlainString()) {
- this.simpleType = null;
- }
- else {
- // Named Simple Type's Name should not be null
- if (this.simpleType.Name != null && this.dttype != null) {
- // if MaxLength is changed, we need to make namedsimpletype annonymous simpletype
- this.simpleType.ConvertToAnnonymousSimpleType();
- this.dttype = null;
- }
- }
- }
- else if (-1 < maxLength) {
- this.SimpleType = SimpleType.CreateLimitedStringType(maxLength);
- }
- }
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataColumnMaxLengthDescr),
- DefaultValue(-1)
- ]
- public int MaxLength {
- get {
- return maxLength;
- }
- set {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_MaxLength|API> %d#, %d\n", ObjectID, value);
- try {
- if (maxLength != value) {
- if (this.ColumnMapping == MappingType.SimpleContent) {
- throw ExceptionBuilder.CannotSetMaxLength2(this);
- }
- if ((DataType != typeof(string)) && (DataType != typeof(SqlString))) {
- throw ExceptionBuilder.HasToBeStringType(this);
- }
- int oldValue = maxLength;
- maxLength = Math.Max(value, -1);
- if (((oldValue < 0) || (value < oldValue)) && (null != table) && table.EnforceConstraints) {
- if (!CheckMaxLength()) {
- maxLength = oldValue;
- throw ExceptionBuilder.CannotSetMaxLength(this, value);
- }
- }
- SetMaxLengthSimpleType();
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataColumnNamespaceDescr)
- ]
- public string Namespace {
- get {
- if (_columnUri == null) {
- if (Table != null && columnMapping != MappingType.Attribute) {
- return Table.Namespace;
- }
- return "";
- }
- return _columnUri;
- }
- set {
- Bid.Trace("<ds.DataColumn.set_Namespace|API> %d#, '%ls'\n", ObjectID, value);
- if (_columnUri != value) {
- if (columnMapping != MappingType.SimpleContent) {
- RaisePropertyChanging("Namespace");
- _columnUri = value;
- }
- else if (value != this.Namespace) {
- throw ExceptionBuilder.CannotChangeNamespace(this.ColumnName);
- }
- }
- }
- }
- private bool ShouldSerializeNamespace() {
- return (_columnUri != null);
- }
- private void ResetNamespace() {
- this.Namespace = null;
- }
- /// <devdoc>
- /// <para>
- /// Gets the position of the column in the <see cref='System.Data.DataColumnCollection'/>
- /// collection.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- Browsable(false),
- DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
- ResDescriptionAttribute(Res.DataColumnOrdinalDescr)
- ]
- public int Ordinal {
- get {
- return _ordinal;
- }
- }
- public void SetOrdinal(int ordinal) {
- if (_ordinal == -1) {
- throw ExceptionBuilder.ColumnNotInAnyTable();
- }
- if (this._ordinal != ordinal) {
- table.Columns.MoveTo(this, ordinal);
- }
- }
- internal void SetOrdinalInternal(int ordinal) {
- //
- if (this._ordinal != ordinal) {
- if (Unique && this._ordinal != -1 && ordinal == -1) {
- UniqueConstraint key = table.Constraints.FindKeyConstraint(this);
- if (key != null)
- table.Constraints.Remove(key);
- }
- // SQLBU 429176: remove the sortIndex when DataColumn is removed
- if ((null != sortIndex) && (-1 == ordinal)) {
- Debug.Assert(2 <= sortIndex.RefCount, "bad sortIndex refcount");
- sortIndex.RemoveRef();
- sortIndex.RemoveRef(); // second should remove it from index collection
- sortIndex = null;
- }
- int originalOrdinal = this._ordinal;
- this._ordinal = ordinal;
- if (originalOrdinal == -1 && this._ordinal != -1) {
- if (Unique) {
- UniqueConstraint key = new UniqueConstraint(this);
- table.Constraints.Add(key);
- }
- }
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets or sets a value
- /// indicating whether the column allows changes once a row has been added to the table.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue(false),
- ResDescriptionAttribute(Res.DataColumnReadOnlyDescr)
- ]
- public bool ReadOnly {
- get {
- return readOnly;
- }
- set {
- Bid.Trace("<ds.DataColumn.set_ReadOnly|API> %d#, %d{bool}\n", ObjectID, value);
- if (readOnly != value) {
- if (!value && expression != null) {
- throw ExceptionBuilder.ReadOnlyAndExpression();
- }
- this.readOnly = value;
- }
- }
- }
- [DebuggerBrowsable(DebuggerBrowsableState.Never)] // don't have debugger view expand this
- private Index SortIndex {
- get {
- if (sortIndex == null) {
- IndexField[] indexDesc = new IndexField[] { new IndexField(this, false) };
- sortIndex = table.GetIndex(indexDesc, DataViewRowState.CurrentRows, (IFilter)null);
- sortIndex.AddRef();
- }
- return sortIndex;
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets the <see cref='System.Data.DataTable'/> to which the column belongs to.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- Browsable(false),
- DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
- ResDescriptionAttribute(Res.DataColumnDataTableDescr)
- ]
- public DataTable Table {
- get {
- return table;
- }
- }
- /// <devdoc>
- /// Internal mechanism for changing the table pointer.
- /// </devdoc>
- internal void SetTable(DataTable table) {
- if (this.table != table) {
- if (this.Computed)
- if ((table == null) ||
- (!table.fInitInProgress && ((table.DataSet == null) || (!table.DataSet.fIsSchemaLoading && !table.DataSet.fInitInProgress)))) {
- // We need to re-bind all expression columns.
- this.DataExpression.Bind(table);
- }
- if (Unique && this.table != null) {
- UniqueConstraint constraint = table.Constraints.FindKeyConstraint(this);
- if (constraint != null)
- table.Constraints.CanRemove(constraint, true);
- }
- this.table = table;
- _storage = null; // empty out storage for reuse.
- }
- }
- private DataRow GetDataRow(int index) {
- return table.recordManager[index];
- }
- /// <devdoc>
- /// This is how data is pushed in and out of the column.
- /// </devdoc>
- internal object this[int record] {
- get {
- table.recordManager.VerifyRecord(record);
- Debug.Assert(null != _storage, "null storage");
- return _storage.Get(record);
- }
- set {
- try {
- table.recordManager.VerifyRecord(record);
- Debug.Assert(null != _storage, "no storage");
- Debug.Assert(null != value, "setting null, expecting dbnull");
- _storage.Set(record, value);
- Debug.Assert(null != this.table, "storage with no DataTable on column");
- }
- catch (Exception e) {
- ExceptionBuilder.TraceExceptionForCapture(e);
- throw ExceptionBuilder.SetFailed(value, this, DataType, e);
- }
- if (AutoIncrement) {
- if (!_storage.IsNull(record)) {
- this.AutoInc.SetCurrentAndIncrement(_storage.Get(record));
- }
- }
- if (Computed) {// if and only if it is Expression column, we will cache LastChangedColumn, otherwise DO NOT
- DataRow dr = GetDataRow(record);
- if (dr != null) {
- // at initialization time (datatable.NewRow(), we would fill the storage with default value, but at that time we wont have datarow)
- dr.LastChangedColumn = this;
- }
- }
- }
- }
- internal void InitializeRecord(int record) {
- Debug.Assert(null != _storage, "no storage");
- _storage.Set(record, DefaultValue);
- }
- internal void SetValue(int record, object value) { // just silently set the value
- try {
- Debug.Assert(null != value, "setting null, expecting dbnull");
- Debug.Assert(null != this.table, "storage with no DataTable on column");
- Debug.Assert(null != _storage, "no storage");
- _storage.Set(record, value);
- }
- catch (Exception e) {
- ExceptionBuilder.TraceExceptionForCapture(e);
- throw ExceptionBuilder.SetFailed(value, this, DataType, e);
- }
- DataRow dr = GetDataRow(record);
- if (dr != null) { // at initialization time (datatable.NewRow(), we would fill the storage with default value, but at that time we wont have datarow)
- dr.LastChangedColumn = this;
- }
- }
- internal void FreeRecord(int record) {
- Debug.Assert(null != _storage, "no storage");
- _storage.Set(record, _storage.NullValue);
- }
- /// <devdoc>
- /// <para>
- /// Gets or sets a value indicating whether the values in each row of the column must be unique.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- DefaultValue(false),
- ResDescriptionAttribute(Res.DataColumnUniqueDescr),
- DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
- ]
- public bool Unique {
- get {
- return unique;
- }
- set {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataColumn.set_Unique|API> %d#, %d{bool}\n", ObjectID, value);
- try {
- if (unique != value) {
- if (value && expression != null) {
- throw ExceptionBuilder.UniqueAndExpression();
- }
- UniqueConstraint oldConstraint = null;
- if (table != null) {
- if (value)
- CheckUnique();
- else {
- for (System.Collections.IEnumerator e = Table.Constraints.GetEnumerator(); e.MoveNext(); ) {
- UniqueConstraint o = (e.Current as UniqueConstraint);
- if ((null != o) && (o.ColumnsReference.Length == 1) && (o.ColumnsReference[0] == this))
- oldConstraint = o;
- }
- Debug.Assert(oldConstraint != null, "Should have found a column to remove from the collection.");
- table.Constraints.CanRemove(oldConstraint, true);
- }
- }
- this.unique = value;
- if (table != null) {
- if (value) {
- // This should not fail due to a duplicate constraint. unique would have
- // already been true if there was an existed UniqueConstraint for this column
- UniqueConstraint constraint = new UniqueConstraint(this);
- Debug.Assert(table.Constraints.FindKeyConstraint(this) == null, "Should not be a duplication constraint in collection");
- table.Constraints.Add(constraint);
- }
- else
- {
- table.Constraints.Remove(oldConstraint);
- //
- }
- }
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- // FxCop Rule; getter not used! WebData 101301; so changing from Property to method
- internal void InternalUnique(bool value) {
- this.unique = value;
- }
- internal string XmlDataType {
- get {
- return dttype;
- }
- set {
- dttype = value;
- }
- }
- internal SimpleType SimpleType {
- get {
- return simpleType;
- }
- set {
- simpleType = value;
- // there is a change, since we are supporting hierarchy(bacause of Names Simple Type) old check (just one leel base check) is wrong
- if (value != null && value.CanHaveMaxLength())
- maxLength = simpleType.MaxLength;// this is temp solution, since we dont let simple content to have
- //maxlength set but for simple type we want to set it, after coming to decision about it , we should
- // use MaxLength property
- }
- }
- /// <devdoc>
- /// <para>Gets the <see cref='System.Data.MappingType'/> of the column.</para>
- /// </devdoc>
- [
- DefaultValue(MappingType.Element),
- ResDescriptionAttribute(Res.DataColumnMappingDescr)
- ]
- public virtual MappingType ColumnMapping {
- get {
- return columnMapping;
- }
- set {
- Bid.Trace("<ds.DataColumn.set_ColumnMapping|API> %d#, %d{ds.MappingType}\n", ObjectID, (int)value);
- if (value != columnMapping) {
- if (value == MappingType.SimpleContent && table != null) {
- int threshold = 0;
- if (columnMapping == MappingType.Element)
- threshold = 1;
- if (this.dataType == typeof(Char))
- throw ExceptionBuilder.CannotSetSimpleContent(ColumnName, this.dataType);
- if (table.XmlText != null && table.XmlText != this)
- throw ExceptionBuilder.CannotAddColumn3();
- if (table.ElementColumnCount > threshold)
- throw ExceptionBuilder.CannotAddColumn4(this.ColumnName);
- }
- RaisePropertyChanging("ColumnMapping");
- if (table != null) {
- if (columnMapping == MappingType.SimpleContent)
- table.xmlText = null;
- if (value == MappingType.Element)
- table.ElementColumnCount++;
- else if (columnMapping == MappingType.Element)
- table.ElementColumnCount--;
- }
- columnMapping = value;
- if (value == MappingType.SimpleContent) {
- _columnUri = null;
- if (table != null) {
- table.XmlText = this;
- }
- this.SimpleType = null;
- }
- }
- }
- }
- internal event PropertyChangedEventHandler PropertyChanging {
- add {
- onPropertyChangingDelegate += value;
- }
- remove {
- onPropertyChangingDelegate -= value;
- }
- }
- internal void CheckColumnConstraint(DataRow row, DataRowAction action) {
- if (table.UpdatingCurrent(row, action)) {
- CheckNullable(row);
- CheckMaxLength(row);
- }
- }
- internal bool CheckMaxLength() {
- if ((0 <= maxLength) && (null != Table) && (0 < Table.Rows.Count)) {
- Debug.Assert(IsStringType, "not a String or SqlString column");
- foreach (DataRow dr in Table.Rows) {
- if (dr.HasVersion(DataRowVersion.Current)) {
- if (maxLength < GetStringLength(dr.GetCurrentRecordNo())) {
- return false;
- }
- }
- }
- }
- return true;
- }
- internal void CheckMaxLength(DataRow dr) {
- if (0 <= maxLength) {
- Debug.Assert(IsStringType, "not a String or SqlString column");
- if (maxLength < GetStringLength(dr.GetDefaultRecord())) {
- throw ExceptionBuilder.LongerThanMaxLength(this);
- }
- }
- }
- internal protected void CheckNotAllowNull() {
- if (_storage == null)
- return;
- if (sortIndex != null) {
- if (sortIndex.IsKeyInIndex(_storage.NullValue)) {// here we do use strong typed NULL for Sql types
- throw ExceptionBuilder.NullKeyValues(ColumnName);
- }
- }
- else { // since we do not have index, we so sequential search
- foreach (DataRow dr in this.table.Rows) {
- if (dr.RowState == DataRowState.Deleted)
- continue;
- if (!implementsINullable) {
- if (dr[this] == DBNull.Value) {
- throw ExceptionBuilder.NullKeyValues(ColumnName);
- }
- }
- else {
- if (DataStorage.IsObjectNull(dr[this])) {
- throw ExceptionBuilder.NullKeyValues(ColumnName);
- }
- }
- }
- }
- }
- internal void CheckNullable(DataRow row) {
- if (!AllowDBNull) {
- Debug.Assert(null != _storage, "no storage");
- if (_storage.IsNull(row.GetDefaultRecord())) {
- throw ExceptionBuilder.NullValues(ColumnName);
- }
- }
- }
- protected void CheckUnique() {
- if (!SortIndex.CheckUnique()) {
- // Throws an exception and the name of any column if its Unique property set to
- // True and non-unique values are found in the column.
- throw ExceptionBuilder.NonUniqueValues(ColumnName);
- }
- }
- internal int Compare(int record1, int record2) {
- Debug.Assert(null != _storage, "null storage");
- return _storage.Compare(record1, record2);
- }
- internal bool CompareValueTo(int record1, object value, bool checkType) {
- // this method is used to make sure value and exact type match.
- int valuesMatch = CompareValueTo(record1, value);
- // if values match according to storage, do extra checks for exact compare
- if (valuesMatch == 0) {
- Type leftType = value.GetType();
- Type rightType = _storage.Get(record1).GetType();
- // if strings, then do exact character by character check
- if (leftType == typeof(System.String) && rightType == typeof(System.String)) {
- return String.CompareOrdinal((string)_storage.Get(record1), (string)value) == 0 ? true : false;
- }
- // make sure same type
- else if (leftType == rightType) {
- return true;
- }
- }
- return false;
- }
- internal int CompareValueTo(int record1, object value) {
- Debug.Assert(null != _storage, "null storage");
- return _storage.CompareValueTo(record1, value);
- }
- internal object ConvertValue(object value) {
- Debug.Assert(null != _storage, "null storage");
- return _storage.ConvertValue(value);
- }
- internal void Copy(int srcRecordNo, int dstRecordNo) {
- Debug.Assert(null != _storage, "null storage");
- _storage.Copy(srcRecordNo, dstRecordNo);
- }
- // 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.
- [MethodImpl(MethodImplOptions.NoInlining)]
- internal DataColumn Clone() {
- DataColumn clone = (DataColumn)Activator.CreateInstance(this.GetType());
- // set All properties
- // clone.columnMapping = columnMapping;
- clone.SimpleType = SimpleType;
- clone.allowNull = allowNull;
- if (null != this.autoInc) {
- clone.autoInc = this.autoInc.Clone();
- }
- clone.caption = caption;
- clone.ColumnName = ColumnName;
- clone._columnUri = _columnUri;
- clone._columnPrefix = _columnPrefix;
- clone.DataType = DataType;
- clone.defaultValue = defaultValue;
- clone.defaultValueIsNull = ((defaultValue == DBNull.Value) || (clone.ImplementsINullable && DataStorage.IsObjectSqlNull(defaultValue))) ? true : false;
- clone.columnMapping = columnMapping;// clone column Mapping since we dont let MaxLength to be set throu API
- //
- clone.readOnly = readOnly;
- clone.MaxLength = MaxLength;
- clone.dttype = dttype;
- clone._dateTimeMode = _dateTimeMode;
- // so if we have set it, we should continue preserving the information
- // ...Extended Properties
- if (this.extendedProperties != null) {
- foreach (Object key in this.extendedProperties.Keys) {
- clone.ExtendedProperties[key] = this.extendedProperties[key];
- }
- }
- return clone;
- }
- /// <devdoc>
- /// <para>Finds a relation that this column is the sole child of or null.</para>
- /// </devdoc>
- internal DataRelation FindParentRelation() {
- DataRelation[] parentRelations = new DataRelation[Table.ParentRelations.Count];
- Table.ParentRelations.CopyTo(parentRelations, 0);
- for (int i = 0; i < parentRelations.Length; i++) {
- DataRelation relation = parentRelations[i];
- DataKey key = relation.ChildKey;
- if (key.ColumnsReference.Length == 1 && key.ColumnsReference[0] == this) {
- return relation;
- }
- }
- // should we throw an exception?
- return null;
- }
- internal object GetAggregateValue(int[] records, AggregateType kind) {
- if (_storage == null) {
- if (kind == AggregateType.Count)
- return 0;
- else
- return DBNull.Value;
- }
- return _storage.Aggregate(records, kind);
- }
- private int GetStringLength(int record) {
- Debug.Assert(null != _storage, "no storage");
- return _storage.GetStringLength(record);
- }
- internal void Init(int record) {
- if (AutoIncrement) {
- object value = this.autoInc.Current;
- this.autoInc.MoveAfter();
- Debug.Assert(null != _storage, "no storage");
- _storage.Set(record, value);
- }
- else
- this[record] = defaultValue;
- }
- internal static bool IsAutoIncrementType(Type dataType) {
- return ((dataType == typeof(Int32)) || (dataType == typeof(Int64)) || (dataType == typeof(Int16)) || (dataType == typeof(Decimal)) || (dataType == typeof(System.Numerics.BigInteger)) ||
- (dataType == typeof(SqlInt32)) || (dataType == typeof(SqlInt64)) || (dataType == typeof(SqlInt16)) || (dataType == typeof(SqlDecimal)));
- }
- private bool IsColumnMappingValid(StorageType typeCode, MappingType mapping) {
- if ((mapping != MappingType.Element) && DataStorage.IsTypeCustomType(typeCode)) {
- return false;
- }
- return true;
- }
- internal bool IsCustomType {
- get {
- if (null != _storage)
- return _storage.IsCustomDefinedType;
- return DataStorage.IsTypeCustomType(DataType);
- }
- }
- internal bool IsValueCustomTypeInstance(object value) {
- // if instance is not a storage supported type (built in or SQL types)
- return (DataStorage.IsTypeCustomType(value.GetType()) && !(value is Type));
- }
- internal bool ImplementsIXMLSerializable {
- get {
- return implementsIXMLSerializable;
- }
- }
- internal bool IsNull(int record) {
- Debug.Assert(null != _storage, "no storage");
- return _storage.IsNull(record);
- }
- /// <devdoc>
- /// Returns true if this column is a part of a Parent or Child key for a relation.
- /// </devdoc>
- internal bool IsInRelation() {
- DataKey key;
- DataRelationCollection rels = table.ParentRelations;
- Debug.Assert(rels != null, "Invalid ParentRelations");
- for (int i = 0; i < rels.Count; i++) {
- key = rels[i].ChildKey;
- Debug.Assert(key.HasValue, "Invalid child key (null)");
- if (key.ContainsColumn(this)) {
- return true;
- }
- }
- rels = table.ChildRelations;
- Debug.Assert(rels != null, "Invalid ChildRelations");
- for (int i = 0; i < rels.Count; i++) {
- key = rels[i].ParentKey;
- Debug.Assert(key.HasValue, "Invalid parent key (null)");
- if (key.ContainsColumn(this)) {
- return true;
- }
- }
- return false;
- }
- internal bool IsMaxLengthViolated() {
- if (MaxLength < 0)
- return true;
- bool error = false;
- object value;
- string errorText = null;
- foreach (DataRow dr in Table.Rows) {
- if (dr.HasVersion(DataRowVersion.Current)) {
- value = dr[this];
- if (!this.isSqlType) {
- if (value != null && value != DBNull.Value && ((string)value).Length > MaxLength) {
- if (errorText == null) {
- errorText = ExceptionBuilder.MaxLengthViolationText(this.ColumnName);
- }
- dr.RowError = errorText;
- dr.SetColumnError(this, errorText);
- error = true;
- }
- }
- else {
- if (!DataStorage.IsObjectNull(value) && ((SqlString)value).Value.Length > MaxLength) {
- if (errorText == null) {
- errorText = ExceptionBuilder.MaxLengthViolationText(this.ColumnName);
- }
- dr.RowError = errorText;
- dr.SetColumnError(this, errorText);
- error = true;
- }
- }
- }
- }
- return error;
- }
- internal bool IsNotAllowDBNullViolated() {//
- Index index = this.SortIndex;
- DataRow[] rows = index.GetRows(index.FindRecords(DBNull.Value));
- for (int i = 0; i < rows.Length; i++) {
- string errorText = ExceptionBuilder.NotAllowDBNullViolationText(this.ColumnName);
- rows[i].RowError = errorText;
- rows[i].SetColumnError(this, errorText);
- }
- return (rows.Length > 0);
- }
- internal void FinishInitInProgress() {
- if (this.Computed)
- BindExpression();
- }
- protected virtual void OnPropertyChanging(PropertyChangedEventArgs pcevent) {
- if (onPropertyChangingDelegate != null)
- onPropertyChangingDelegate(this, pcevent);
- }
- protected internal void RaisePropertyChanging(string name) {
- OnPropertyChanging(new PropertyChangedEventArgs(name));
- }
- private void InsureStorage() {
- if (_storage == null) {
- _storage = DataStorage.CreateStorage(this, dataType, _storageType);
- }
- }
- internal void SetCapacity(int capacity) {
- InsureStorage();
- _storage.SetCapacity(capacity);
- }
- private bool ShouldSerializeDefaultValue() {
- return (!DefaultValueIsNull);
- }
- internal void OnSetDataSet() {
- }
- // Returns the <see cref='System.Data.DataColumn.Expression'/> of the column, if one exists.
- public override string ToString() {
- if (this.expression == null)
- return this.ColumnName;
- else
- return this.ColumnName + " + " + this.Expression;
- }
- internal object ConvertXmlToObject(string s) {
- Debug.Assert(s != null, "Caller is resposible for missing element/attribure case");
- InsureStorage();
- return _storage.ConvertXmlToObject(s);
- }
- internal object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute xmlAttrib) {
- InsureStorage();
- return _storage.ConvertXmlToObject(xmlReader, xmlAttrib);
- }
- internal string ConvertObjectToXml(object value) {
- Debug.Assert(value != null && (value != DBNull.Value), "Caller is resposible for checking on DBNull");
- InsureStorage();
- return _storage.ConvertObjectToXml(value);
- }
- internal void ConvertObjectToXml(object value, XmlWriter xmlWriter, XmlRootAttribute xmlAttrib) {
- Debug.Assert(value != null && (value != DBNull.Value), "Caller is resposible for checking on DBNull");
- InsureStorage();
- _storage.ConvertObjectToXml(value, xmlWriter, xmlAttrib);
- }
- internal object GetEmptyColumnStore(int recordCount) {
- InsureStorage();
- return _storage.GetEmptyStorageInternal(recordCount);
- }
- internal void CopyValueIntoStore(int record, object store, BitArray nullbits, int storeIndex) {
- Debug.Assert(null != _storage, "no storage");
- _storage.CopyValueInternal(record, store, nullbits, storeIndex);
- }
- internal void SetStorage(object store, BitArray nullbits) {
- InsureStorage();
- _storage.SetStorageInternal(store, nullbits);
- }
- internal void AddDependentColumn(DataColumn expressionColumn) {
- if (dependentColumns == null) {
- dependentColumns = new List<DataColumn>();
- }
- Debug.Assert(!dependentColumns.Contains(expressionColumn), "duplicate column - expected to be unique");
- dependentColumns.Add(expressionColumn);
- this.table.AddDependentColumn(expressionColumn);
- }
- internal void RemoveDependentColumn(DataColumn expressionColumn) {
- if (dependentColumns != null && dependentColumns.Contains(expressionColumn)) {
- dependentColumns.Remove(expressionColumn);
- }
- this.table.RemoveDependentColumn(expressionColumn);
- }
- internal void HandleDependentColumnList(DataExpression oldExpression, DataExpression newExpression) {
- DataColumn[] dependency;
- // remove this column from the dependentColumn list of the columns this column depends on.
- if (oldExpression != null) {
- dependency = oldExpression.GetDependency();
- foreach (DataColumn col in dependency) {
- Debug.Assert(null != col, "null datacolumn in expression dependencies");
- col.RemoveDependentColumn(this);
- if (col.table != this.table) {
- this.table.RemoveDependentColumn(this);
- }
- }
- this.table.RemoveDependentColumn(this);
- }
- if (newExpression != null) {
- // get the list of columns that this expression depends on
- dependency = newExpression.GetDependency();
- // add this column to dependent column list of each column this column depends on
- foreach (DataColumn col in dependency) {
- col.AddDependentColumn(this);
- if (col.table != this.table) {
- this.table.AddDependentColumn(this);
- }
- }
- this.table.AddDependentColumn(this);
- }
- }
- }
- internal abstract class AutoIncrementValue {
- private bool auto;
- internal bool Auto {
- get { return this.auto; }
- set { this.auto = value; }
- }
- internal abstract object Current { get; set; }
- internal abstract long Seed { get; set; }
- internal abstract long Step { get; set; }
- internal abstract Type DataType { get; }
- internal abstract void SetCurrent(object value, IFormatProvider formatProvider);
- internal abstract void SetCurrentAndIncrement(object value);
- internal abstract void MoveAfter();
- internal AutoIncrementValue Clone() {
- AutoIncrementValue clone = (this is AutoIncrementInt64) ? (AutoIncrementValue)new AutoIncrementInt64() : (AutoIncrementValue)new AutoIncrementBigInteger();
- clone.Auto = this.Auto;
- clone.Seed = this.Seed;
- clone.Step = this.Step;
- clone.Current = this.Current;
- return clone;
- }
- }
- /// <summary>the auto stepped value with Int64 representation</summary>
- /// <remarks>use unchecked behavior for Dev10 Bug 568510</remarks>
- internal sealed class AutoIncrementInt64 : AutoIncrementValue {
- /// <summary>the last returned auto incremented value</summary>
- private System.Int64 current;
- /// <summary>the initial value use to set current</summary>
- private System.Int64 seed;
- /// <summary>the value by which to offset the next value</summary>
- private System.Int64 step = 1;
- /// <summary>Gets and sets the current auto incremented value to use</summary>
- internal override object Current {
- get { return this.current; }
- set { this.current = (Int64)value; }
- }
- internal override Type DataType { get { return typeof(System.Int64); } }
- /// <summary>Get and sets the initial seed value.</summary>
- internal override long Seed {
- get { return this.seed; }
- set {
- if ((this.current == this.seed) || this.BoundaryCheck(value)) {
- this.current = value;
- }
- this.seed = value;
- }
- }
- /// <summary>Get and sets the stepping value.</summary>
- /// <exception cref="ArugmentException">if value is 0</exception>
- internal override long Step {
- get { return this.step; }
- set {
- if (0 == value) {
- throw ExceptionBuilder.AutoIncrementSeed();
- }
- if (this.step != value) {
- if (this.current != this.Seed) {
- this.current = unchecked(this.current - this.step + value);
- }
- this.step = value;
- }
- }
- }
- internal override void MoveAfter() {
- this.current = unchecked(this.current + this.step);
- }
- internal override void SetCurrent(object value, IFormatProvider formatProvider) {
- this.current = Convert.ToInt64(value, formatProvider);
- }
- internal override void SetCurrentAndIncrement(object value) {
- Debug.Assert(null != value && DataColumn.IsAutoIncrementType(value.GetType()) && !(value is System.Numerics.BigInteger), "unexpected value for autoincrement");
- System.Int64 v = (Int64)SqlConvert.ChangeType2(value, StorageType.Int64, typeof(Int64), CultureInfo.InvariantCulture);
- if (this.BoundaryCheck(v)) {
- this.current = unchecked(v + this.step);
- }
- }
- private bool BoundaryCheck(System.Numerics.BigInteger value) {
- return (((this.step < 0) && (value <= this.current)) || ((0 < this.step) && (this.current <= value)));
- }
- }
- /// <summary>the auto stepped value with BigInteger representation</summary>
- internal sealed class AutoIncrementBigInteger : AutoIncrementValue {
- /// <summary>the current auto incremented value to use</summary>
- private System.Numerics.BigInteger current;
- /// <summary>the initial value use to set current</summary>
- private System.Int64 seed;
- /// <summary>the value by which to offset the next value</summary>
- private System.Numerics.BigInteger step = 1;
- /// <summary>Gets and sets the current auto incremented value to use</summary>
- internal override object Current {
- get { return this.current; }
- set { this.current = (System.Numerics.BigInteger)value; }
- }
- internal override Type DataType { get { return typeof(System.Numerics.BigInteger); } }
- /// <summary>Get and sets the initial seed value.</summary>
- internal override long Seed {
- get { return this.seed; }
- set {
- if ((this.current == this.seed) || this.BoundaryCheck(value)) {
- this.current = value;
- }
- this.seed = value;
- }
- }
- /// <summary>Get and sets the stepping value.</summary>
- /// <exception cref="ArugmentException">if value is 0</exception>
- internal override long Step {
- get { return (long)this.step; }
- set {
- if (0 == value) {
- throw ExceptionBuilder.AutoIncrementSeed();
- }
- if (this.step != value) {
- if (this.current != this.Seed) {
- this.current = checked(this.current - this.step + value);
- }
- this.step = value;
- }
- }
- }
- internal override void MoveAfter() {
- this.current = checked(this.current + this.step);
- }
- internal override void SetCurrent(object value, IFormatProvider formatProvider) {
- this.current = BigIntegerStorage.ConvertToBigInteger(value, formatProvider);
- }
- internal override void SetCurrentAndIncrement(object value) {
- System.Numerics.BigInteger v = (System.Numerics.BigInteger)value;
- if (this.BoundaryCheck(v)) {
- this.current = v + this.step;
- }
- }
- private bool BoundaryCheck(System.Numerics.BigInteger value) {
- return (((this.step < 0) && (value <= this.current)) || ((0 < this.step) && (this.current <= value)));
- }
- }
- }
|