2 // System.Data.DataColumn.cs
\r
5 // Franklin Wise (gracenote@earthlink.net)
\r
6 // Christopher Podurgiel (cpodurgiel@msn.com)
\r
7 // Rodrigo Moya (rodrigo@ximian.com)
\r
8 // Daniel Morgan (danmorg@sc.rr.com)
\r
9 // Tim Coleman (tim@timcoleman.com)
\r
11 // (C) Copyright 2002, Franklin Wise
\r
12 // (C) Chris Podurgiel
\r
13 // (C) Ximian, Inc 2002
\r
14 // Copyright (C) Tim Coleman, 2002
\r
15 // Copyright (C) Daniel Morgan, 2002, 2003
\r
19 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
\r
21 // Permission is hereby granted, free of charge, to any person obtaining
\r
22 // a copy of this software and associated documentation files (the
\r
23 // "Software"), to deal in the Software without restriction, including
\r
24 // without limitation the rights to use, copy, modify, merge, publish,
\r
25 // distribute, sublicense, and/or sell copies of the Software, and to
\r
26 // permit persons to whom the Software is furnished to do so, subject to
\r
27 // the following conditions:
\r
29 // The above copyright notice and this permission notice shall be
\r
30 // included in all copies or substantial portions of the Software.
\r
32 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
33 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
34 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
35 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
36 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
37 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
38 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
42 using System.ComponentModel;
\r
43 using System.Reflection;
\r
44 using System.Collections;
\r
45 using System.Data.Common;
\r
46 using System.Data.SqlTypes;
\r
47 using System.Globalization;
\r
48 using Mono.Data.SqlExpressions;
\r
50 namespace System.Data {
\r
51 internal delegate void DelegateColumnValueChange(DataColumn column, DataRow row, object proposedValue);
\r
54 /// Summary description for DataColumn.
\r
57 [Editor ("Microsoft.VSDesigner.Data.Design.DataColumnEditor, " + Consts.AssemblyMicrosoft_VSDesigner,
\r
58 "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
\r
59 [ToolboxItem (false)]
\r
60 [DefaultProperty ("ColumnName")]
\r
61 [DesignTimeVisible (false)]
\r
62 public class DataColumn : MarshalByValueComponent
\r
65 EventHandlerList _eventHandlers = new EventHandlerList ();
\r
67 //used for constraint validation
\r
68 //if an exception is fired during this event the change should be canceled
\r
70 internal event DelegateColumnValueChange ValidateColumnValueChange;
\r
72 //used for FK Constraint Cascading rules
\r
74 internal event DelegateColumnValueChange ColumnValueChanging;
\r
76 static readonly object _propertyChangedKey = new object ();
\r
77 internal event PropertyChangedEventHandler PropertyChanged {
\r
78 add { _eventHandlers.AddHandler (_propertyChangedKey, value); }
\r
79 remove { _eventHandlers.RemoveHandler (_propertyChangedKey, value); }
\r
86 private bool _allowDBNull = true;
\r
87 private bool _autoIncrement;
\r
88 private long _autoIncrementSeed;
\r
89 private long _autoIncrementStep = 1;
\r
90 private long _nextAutoIncrementValue;
\r
91 private string _caption;
\r
92 private MappingType _columnMapping;
\r
93 private string _columnName = String.Empty;
\r
94 private object _defaultValue = GetDefaultValueForType (null);
\r
95 private string _expression;
\r
96 private IExpression _compiledExpression;
\r
97 private PropertyCollection _extendedProperties = new PropertyCollection ();
\r
98 private int _maxLength = -1; //-1 represents no length limit
\r
99 private string _nameSpace;
\r
100 private int _ordinal = -1; //-1 represents not part of a collection
\r
101 private string _prefix = String.Empty;
\r
102 private bool _readOnly;
\r
103 private DataTable _table;
\r
104 private bool _unique;
\r
105 private DataContainer _dataContainer;
\r
107 #endregion // Fields
\r
109 #region Constructors
\r
111 public DataColumn() : this(String.Empty, typeof (string), String.Empty, MappingType.Element)
\r
115 //TODO: Ctor init vars directly
\r
116 public DataColumn(string columnName): this(columnName, typeof (string), String.Empty, MappingType.Element)
\r
120 public DataColumn(string columnName, Type dataType): this(columnName, dataType, String.Empty, MappingType.Element)
\r
124 public DataColumn( string columnName, Type dataType,
\r
125 string expr): this(columnName, dataType, expr, MappingType.Element)
\r
129 public DataColumn(string columnName, Type dataType,
\r
130 string expr, MappingType type)
\r
132 ColumnName = (columnName == null ? String.Empty : columnName);
\r
134 if (dataType == null)
\r
135 throw new ArgumentNullException("dataType");
\r
137 DataType = dataType;
\r
138 Expression = expr == null ? String.Empty : expr;
\r
139 ColumnMapping = type;
\r
145 internal object this[int index] {
\r
147 return DataContainer[index];
\r
150 if ( !(value == null && AutoIncrement) ) {
\r
152 DataContainer[index] = value;
\r
154 catch(Exception e) {
\r
155 throw new ArgumentException(String.Format("{0}. Couldn't store <{1}> in Column named '{2}'. Expected type is {3}.",
\r
156 e.Message, value, ColumnName, DataType.Name), e);
\r
160 if ( AutoIncrement && !DataContainer.IsNull(index) ) {
\r
161 long value64 = Convert.ToInt64(value);
\r
162 UpdateAutoIncrementValue(value64);
\r
168 DataSetDateTime _datetimeMode = DataSetDateTime.UnspecifiedLocal;
\r
169 [DefaultValue (DataSetDateTime.UnspecifiedLocal)]
\r
170 [RefreshProperties (RefreshProperties.All)]
\r
171 public DataSetDateTime DateTimeMode {
\r
172 get { return _datetimeMode; }
\r
174 if (DataType != typeof (DateTime))
\r
175 throw new InvalidOperationException ("The DateTimeMode can be set only on DataColumns of type DateTime.");
\r
177 if (!Enum.IsDefined (typeof (DataSetDateTime), value))
\r
178 throw new InvalidEnumArgumentException (
\r
179 string.Format (CultureInfo.InvariantCulture,
\r
180 "The {0} enumeration value, {1}, is invalid",
\r
181 typeof (DataSetDateTime).Name, value));
\r
183 if (_datetimeMode == value)
\r
185 if (_table == null || _table.Rows.Count == 0) {
\r
186 _datetimeMode = value;
\r
189 if ((_datetimeMode == DataSetDateTime.Unspecified || _datetimeMode == DataSetDateTime.UnspecifiedLocal)
\r
190 && (value == DataSetDateTime.Unspecified || value == DataSetDateTime.UnspecifiedLocal)) {
\r
191 _datetimeMode = value;
\r
195 throw new InvalidOperationException ( String.Format (
\r
196 "Cannot change DateTimeMode from '{0}' to '{1}' " +
\r
197 "once the table has data.",_datetimeMode, value));
\r
202 [DataCategory ("Data")]
\r
204 [DataSysDescription ("Indicates whether null values are allowed in this column.")]
\r
206 [DefaultValue (true)]
\r
207 public bool AllowDBNull
\r
210 return _allowDBNull;
\r
213 //TODO: If we are a part of the table and this value changes
\r
214 //we need to validate that all the existing values conform to the new setting
\r
218 _allowDBNull = true;
\r
222 //if Value == false case
\r
223 if (null != _table)
\r
225 if (_table.Rows.Count > 0)
\r
227 bool nullsFound = false;
\r
228 for(int r = 0; r < _table.Rows.Count; r++) {
\r
229 DataRow row = _table.Rows[r];
\r
230 DataRowVersion version = row.HasVersion (DataRowVersion.Default) ?
\r
231 DataRowVersion.Default : DataRowVersion.Original;
\r
232 if(row.IsNull(this, version)) {
\r
239 throw new DataException("Column '" + ColumnName + "' has null values in it.");
\r
240 //TODO: Validate no null values exist
\r
241 //do we also check different versions of the row??
\r
245 _allowDBNull = value;
\r
250 /// Gets or sets a value indicating whether the column automatically increments the value of the column for new rows added to the table.
\r
253 /// If the type of this column is not Int16, Int32, or Int64 when this property is set,
\r
254 /// the DataType property is coerced to Int32. An exception is generated if this is a computed column
\r
255 /// (that is, the Expression property is set.) The incremented value is used only if the row's value for this column,
\r
256 /// when added to the columns collection, is equal to the default value.
\r
258 [DataCategory ("Data")]
\r
260 [DataSysDescription ("Indicates whether the column automatically increments itself for new rows added to the table. The type of this column must be Int16, Int32, or Int64.")]
\r
262 [DefaultValue (false)]
\r
263 [RefreshProperties (RefreshProperties.All)]
\r
264 public bool AutoIncrement
\r
267 return _autoIncrement;
\r
272 //Can't be true if this is a computed column
\r
273 if (Expression != string.Empty)
\r
275 throw new ArgumentException("Can not Auto Increment a computed column.");
\r
278 if ( DefaultValue != DBNull.Value ) {
\r
279 throw new ArgumentException("Can not set AutoIncrement while" +
\r
280 " default value exists for this column.");
\r
283 if(!CanAutoIncrement(DataType))
\r
285 DataType = typeof(Int32);
\r
288 if (_table != null)
\r
289 _table.Columns.UpdateAutoIncrement(this,true);
\r
293 if (_table != null)
\r
294 _table.Columns.UpdateAutoIncrement(this,false);
\r
296 _autoIncrement = value;
\r
300 [DataCategory ("Data")]
\r
302 [DataSysDescription ("Indicates the starting value for an AutoIncrement column.")]
\r
305 public long AutoIncrementSeed
\r
308 return _autoIncrementSeed;
\r
311 _autoIncrementSeed = value;
\r
312 _nextAutoIncrementValue = _autoIncrementSeed;
\r
316 [DataCategory ("Data")]
\r
318 [DataSysDescription ("Indicates the increment used by an AutoIncrement column.")]
\r
321 public long AutoIncrementStep
\r
324 return _autoIncrementStep;
\r
327 _autoIncrementStep = value;
\r
331 internal void UpdateAutoIncrementValue(long value64)
\r
333 if (_autoIncrementStep > 0 ) {
\r
334 if (value64 >= _nextAutoIncrementValue) {
\r
335 _nextAutoIncrementValue = value64;
\r
336 AutoIncrementValue ();
\r
339 else if (value64 <= _nextAutoIncrementValue) {
\r
340 AutoIncrementValue ();
\r
344 internal long AutoIncrementValue ()
\r
346 long currentValue = _nextAutoIncrementValue;
\r
347 _nextAutoIncrementValue += AutoIncrementStep;
\r
348 return currentValue;
\r
351 internal long GetAutoIncrementValue ()
\r
353 return _nextAutoIncrementValue;
\r
356 internal void SetDefaultValue(int index) {
\r
358 this[index] = _nextAutoIncrementValue;
\r
360 DataContainer.CopyValue(Table.DefaultValuesRowIndex, index);
\r
363 [DataCategory ("Data")]
\r
365 [DataSysDescription ("Indicates the default user-interface caption for this column.")]
\r
367 public string Caption
\r
370 if(_caption == null)
\r
377 value = String.Empty;
\r
384 [DataSysDescription ("Indicates how this column persists in XML: as an attribute, element, simple content node, or nothing.")]
\r
386 [DefaultValue (MappingType.Element)]
\r
387 public virtual MappingType ColumnMapping
\r
390 return _columnMapping;
\r
393 _columnMapping = value;
\r
397 [DataCategory ("Data")]
\r
399 [DataSysDescription ("Indicates the name used to look up this column in the Columns collection of a DataTable.")]
\r
401 [RefreshProperties (RefreshProperties.All)]
\r
402 [DefaultValue ("")]
\r
403 public string ColumnName
\r
406 return _columnName;
\r
410 value = String.Empty;
\r
412 CultureInfo info = Table != null ? Table.Locale : CultureInfo.CurrentCulture;
\r
413 if (String.Compare(value, _columnName, true, info) != 0) {
\r
414 if (Table != null) {
\r
415 if (value.Length == 0)
\r
416 throw new ArgumentException("ColumnName is required when it is part of a DataTable.");
\r
418 Table.Columns.RegisterName(value, this);
\r
419 if (_columnName.Length > 0)
\r
420 Table.Columns.UnregisterName(_columnName);
\r
423 RaisePropertyChanging("ColumnName");
\r
424 _columnName = value;
\r
427 Table.ResetPropertyDescriptorsCache();
\r
429 else if (String.Compare(value, _columnName, false, info) != 0) {
\r
430 RaisePropertyChanging("ColumnName");
\r
431 _columnName = value;
\r
434 Table.ResetPropertyDescriptorsCache();
\r
439 [DataCategory ("Data")]
\r
441 [DataSysDescription ("Indicates the type of data stored in this column.")]
\r
443 [DefaultValue (typeof (string))]
\r
444 [RefreshProperties (RefreshProperties.All)]
\r
445 [TypeConverterAttribute (typeof (ColumnTypeConverter))]
\r
446 public Type DataType
\r
449 return DataContainer.Type;
\r
453 if ( value == null )
\r
456 if ( _dataContainer != null ) {
\r
457 if ( value == _dataContainer.Type )
\r
460 // check if data already exists can we change the datatype
\r
461 if ( _dataContainer.Capacity > 0 )
\r
462 throw new ArgumentException("The column already has data stored.");
\r
465 if (null != GetParentRelation () || null != GetChildRelation ())
\r
466 throw new InvalidConstraintException ("Cannot change datatype, " +
\r
467 "when column is part of a relation");
\r
469 Type prevType = _dataContainer != null ? _dataContainer.Type : null; // current
\r
472 if (_dataContainer != null && _dataContainer.Type == typeof (DateTime))
\r
473 _datetimeMode = DataSetDateTime.UnspecifiedLocal;
\r
475 _dataContainer = DataContainer.Create (value, this);
\r
477 //Check AutoIncrement status, make compatible datatype
\r
478 if(AutoIncrement == true) {
\r
479 // we want to check that the datatype is supported?
\r
480 TypeCode typeCode = Type.GetTypeCode(value);
\r
482 if(typeCode != TypeCode.Int16 &&
\r
483 typeCode != TypeCode.Int32 &&
\r
484 typeCode != TypeCode.Int64) {
\r
485 AutoIncrement = false;
\r
489 if (DefaultValue != GetDefaultValueForType (prevType))
\r
490 SetDefaultValue (DefaultValue, true);
\r
493 _defaultValue = GetDefaultValueForType (DataType);
\r
501 /// <remarks>When AutoIncrement is set to true, there can be no default value.</remarks>
\r
502 /// <exception cref="System.InvalidCastException"></exception>
\r
503 /// <exception cref="System.ArgumentException"></exception>
\r
504 [DataCategory ("Data")]
\r
506 [DataSysDescription ("Indicates the default column value used when adding new rows to the table.")]
\r
508 [TypeConverterAttribute (typeof (System.Data.DefaultValueTypeConverter))]
\r
509 public object DefaultValue
\r
512 return _defaultValue;
\r
516 if (AutoIncrement) {
\r
517 throw new ArgumentException("Can not set default value while" +
\r
518 " AutoIncrement is true on this column.");
\r
520 SetDefaultValue (value, false);
\r
524 void SetDefaultValue (object value, bool forcedTypeCheck)
\r
528 if (forcedTypeCheck|| !this._defaultValue.Equals(value)) {
\r
529 if (value == null) {
\r
530 tmpObj = DBNull.Value;
\r
536 if (!this.DataType.IsInstanceOfType (tmpObj) && tmpObj != DBNull.Value) {
\r
538 //Casting to the new type
\r
539 tmpObj= Convert.ChangeType(tmpObj,this.DataType);
\r
541 catch (InvalidCastException) {
\r
542 string msg = String.Format ("Default Value of type '{0}' is not compatible with column type '{1}'", tmpObj.GetType (), DataType);
\r
544 throw new DataException(msg);
\r
546 throw new ArgumentException(msg);
\r
551 if (tmpObj == DBNull.Value)
\r
552 tmpObj = GetDefaultValueForType (DataType);
\r
554 _defaultValue = tmpObj;
\r
557 // store default value in the table if already belongs to
\r
558 if (Table != null && Table.DefaultValuesRowIndex != -1) {
\r
559 DataContainer[Table.DefaultValuesRowIndex] = _defaultValue;
\r
564 [DataCategory ("Data")]
\r
566 [DataSysDescription ("Indicates the value that this column computes for each row based on other columns instead of taking user input.")]
\r
568 [DefaultValue ("")]
\r
569 [RefreshProperties (RefreshProperties.All)]
\r
570 public string Expression
\r
573 return _expression;
\r
577 value = String.Empty;
\r
579 if (value != String.Empty)
\r
582 if (AutoIncrement || Unique)
\r
583 throw new ArgumentException("Cannot create an expression on a column that has AutoIncrement or Unique.");
\r
587 for (int i = 0; i < Table.Constraints.Count; i++)
\r
589 if (Table.Constraints[i].IsColumnContained(this))
\r
590 throw new ArgumentException(String.Format("Cannot set Expression property on column {0}, because it is a part of a constraint.", ColumnName));
\r
594 Parser parser = new Parser ();
\r
595 IExpression compiledExpression = parser.Compile (value);
\r
599 if (compiledExpression.DependsOn(this))
\r
600 throw new ArgumentException("Cannot set Expression property due to circular reference in the expression.");
\r
601 // Check if expression is ok
\r
602 if (Table.Rows.Count == 0)
\r
603 compiledExpression.Eval (Table.NewRow());
\r
605 compiledExpression.Eval (Table.Rows[0]);
\r
608 _compiledExpression = compiledExpression;
\r
612 _compiledExpression = null;
\r
613 if (Table != null) {
\r
614 int defaultValuesRowIndex = Table.DefaultValuesRowIndex;
\r
615 if ( defaultValuesRowIndex != -1)
\r
616 DataContainer.FillValues(defaultValuesRowIndex);
\r
619 _expression = value;
\r
623 internal IExpression CompiledExpression {
\r
624 get { return _compiledExpression; }
\r
627 [Browsable (false)]
\r
628 [DataCategory ("Data")]
\r
630 [DataSysDescription ("The collection that holds custom user information.")]
\r
632 public PropertyCollection ExtendedProperties
\r
635 return _extendedProperties;
\r
638 internal set { _extendedProperties = value; }
\r
642 [DataCategory ("Data")]
\r
644 [DataSysDescription ("Indicates the maximum length of the value this column allows. ")]
\r
646 [DefaultValue (-1)]
\r
647 public int MaxLength
\r
650 //Default == -1 no max length
\r
655 _columnMapping == MappingType.SimpleContent)
\r
656 throw new ArgumentException (String.Format ("Cannot set MaxLength property on '{0}' column which is mapped to SimpleContent.", ColumnName));
\r
657 //only applies to string columns
\r
658 _maxLength = value;
\r
662 [DataCategory ("Data")]
\r
664 [DataSysDescription ("Indicates the XML uri for elements or attributes stored in this column.")]
\r
666 public string Namespace
\r
669 if (_nameSpace != null)
\r
673 if ((Table != null) && (_columnMapping != MappingType.Attribute))
\r
675 return Table.Namespace;
\r
677 return String.Empty;
\r
680 _nameSpace = value;
\r
684 //Need a good way to set the Ordinal when the column is added to a columnCollection.
\r
685 [Browsable (false)]
\r
686 [DataCategory ("Data")]
\r
688 [DataSysDescription ("Indicates the index of this column in the Columns collection.")]
\r
690 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
\r
691 public int Ordinal {
\r
692 get { return _ordinal; }
\r
694 internal set { _ordinal = value; }
\r
699 public void SetOrdinal (int ordinal)
\r
701 if (_ordinal == -1)
\r
702 throw new ArgumentException ("Column must belong to a table.");
\r
703 _table.Columns.MoveColumn (_ordinal, ordinal);
\r
704 _ordinal = ordinal;
\r
707 internal void SetOrdinal(int ordinal)
\r
709 _ordinal = ordinal;
\r
713 [DataCategory ("Data")]
\r
715 [DataSysDescription ("Indicates the Prefix used for this DataColumn in xml representation.")]
\r
717 [DefaultValue ("")]
\r
718 public string Prefix
\r
725 value = String.Empty;
\r
730 [DataCategory ("Data")]
\r
732 [DataSysDescription ("Indicates whether this column allows changes once a row has been added to the table.")]
\r
734 [DefaultValue (false)]
\r
735 public bool ReadOnly
\r
745 [Browsable (false)]
\r
746 [DataCategory ("Data")]
\r
748 [DataSysDescription ("Returns the DataTable to which this column belongs.")]
\r
750 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
\r
751 public DataTable Table
\r
763 [DataCategory ("Data")]
\r
765 [DataSysDescription ("Indicates whether this column should restrict its values in the rows of the table to be unique.")]
\r
767 [DefaultValue (false)]
\r
768 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
\r
776 if (_unique == value)
\r
779 // Set the property value, so that when adding/removing the constraint
\r
780 // we dont run into recursive issues.
\r
783 if (_table == null)
\r
788 if (Expression != null && Expression != String.Empty)
\r
789 throw new ArgumentException("Cannot change Unique property for the expression column.");
\r
791 _table.Constraints.Add(null, this, false);
\r
794 UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet (_table.Constraints,
\r
795 new DataColumn[] {this});
\r
796 _table.Constraints.Remove (uc);
\r
798 } catch (Exception e) {
\r
805 internal DataContainer DataContainer {
\r
807 return _dataContainer;
\r
811 internal static bool CanAutoIncrement(Type type) {
\r
812 switch (Type.GetTypeCode(type)) {
\r
813 case TypeCode.Int16:
\r
814 case TypeCode.Int32:
\r
815 case TypeCode.Int64:
\r
816 case TypeCode.Decimal:
\r
823 #endregion // Properties
\r
828 internal DataColumn Clone() {
\r
829 DataColumn copy = new DataColumn ();
\r
831 // Copy all the properties of column
\r
832 copy._allowDBNull = _allowDBNull;
\r
833 copy._autoIncrement = _autoIncrement;
\r
834 copy._autoIncrementSeed = _autoIncrementSeed;
\r
835 copy._autoIncrementStep = _autoIncrementStep;
\r
836 copy._caption = _caption;
\r
837 copy._columnMapping = _columnMapping;
\r
838 copy._columnName = _columnName;
\r
840 copy.DataType = DataType;
\r
841 copy._defaultValue = _defaultValue;
\r
842 copy._expression = _expression;
\r
843 //Copy.ExtendedProperties
\r
844 copy._maxLength = _maxLength;
\r
845 copy._nameSpace = _nameSpace;
\r
846 copy._prefix = _prefix;
\r
847 copy._readOnly = _readOnly;
\r
849 //we do not copy the unique value - it will be copyied when copying the constraints.
\r
850 //Copy.Unique = Column.Unique;
\r
852 if (DataType == typeof (DateTime))
\r
853 copy.DateTimeMode = _datetimeMode;
\r
860 /// Sets unique true whithout creating Constraint
\r
862 internal void SetUnique()
\r
868 internal void AssertCanAddToCollection()
\r
870 //Check if Default Value is set and AutoInc is set
\r
874 protected internal void CheckNotAllowNull ()
\r
876 throw new NotImplementedException ();
\r
880 protected void CheckUnique ()
\r
882 throw new NotImplementedException ();
\r
885 protected internal virtual void
\r
886 OnPropertyChanging (PropertyChangedEventArgs pcevent) {
\r
887 PropertyChangedEventHandler eh = _eventHandlers [_propertyChangedKey] as PropertyChangedEventHandler;
\r
890 eh (this, pcevent);
\r
893 protected internal void RaisePropertyChanging(string name) {
\r
894 PropertyChangedEventArgs e = new PropertyChangedEventArgs (name);
\r
895 OnPropertyChanging (e);
\r
899 /// Gets the Expression of the column, if one exists.
\r
901 /// <returns>The Expression value, if the property is set;
\r
902 /// otherwise, the ColumnName property.</returns>
\r
903 public override string ToString()
\r
905 if (_expression != string.Empty)
\r
906 return ColumnName + " + " + _expression;
\r
911 internal void SetTable (DataTable table) {
\r
912 if(_table != null) { // serves as double check while adding to a table
\r
913 throw new ArgumentException ("The column already belongs to a different table");
\r
916 // this will get called by DataTable
\r
917 // and DataColumnCollection
\r
919 // if the DataColumn is marked as Unique and then
\r
920 // added to a DataTable , then a UniqueConstraint
\r
921 // should be created
\r
922 UniqueConstraint uc = new UniqueConstraint(this);
\r
923 _table.Constraints.Add (uc);
\r
926 // allocate space in the column data container
\r
927 DataContainer.Capacity = _table.RecordCache.CurrentCapacity;
\r
929 int defaultValuesRowIndex = _table.DefaultValuesRowIndex;
\r
930 if ( defaultValuesRowIndex != -1) {
\r
931 // store default value in the table
\r
932 DataContainer[defaultValuesRowIndex] = _defaultValue;
\r
933 // Set all the values in data container to default
\r
934 // it's cheaper that raise event on each row.
\r
935 DataContainer.FillValues(defaultValuesRowIndex);
\r
939 // Returns true if all the same collumns are in columnSet and compareSet
\r
940 internal static bool AreColumnSetsTheSame(DataColumn[] columnSet, DataColumn[] compareSet)
\r
942 if (null == columnSet && null == compareSet)
\r
945 if (null == columnSet || null == compareSet)
\r
948 if (columnSet.Length != compareSet.Length)
\r
951 foreach (DataColumn col in columnSet) {
\r
952 bool matchFound = false;
\r
953 foreach (DataColumn compare in compareSet) {
\r
954 if (col == compare)
\r
964 internal int CompareValues (int index1, int index2)
\r
966 return DataContainer.CompareValues(index1, index2);
\r
970 /// Returns the data relation, which contains this column.
\r
971 /// This searches in current table's parent relations.
\r
974 /// DataRelation if found otherwise null.
\r
976 private DataRelation GetParentRelation ()
\r
978 if (_table == null)
\r
980 foreach (DataRelation rel in _table.ParentRelations)
\r
981 if (rel.Contains (this))
\r
988 /// Returns the data relation, which contains this column.
\r
989 /// This searches in current table's child relations.
\r
992 /// DataRelation if found otherwise null.
\r
994 private DataRelation GetChildRelation ()
\r
996 if (_table == null)
\r
998 foreach (DataRelation rel in _table.ChildRelations)
\r
999 if (rel.Contains (this))
\r
1004 internal void ResetColumnInfo ()
\r
1008 if (_compiledExpression != null)
\r
1009 _compiledExpression.ResetExpression ();
\r
1012 internal bool DataTypeMatches (DataColumn col)
\r
1014 if (DataType != col.DataType)
\r
1017 if (DataType != typeof (DateTime))
\r
1020 if (DateTimeMode == col.DateTimeMode)
\r
1023 if (DateTimeMode == DataSetDateTime.Local || DateTimeMode == DataSetDateTime.Utc)
\r
1026 if (col.DateTimeMode == DataSetDateTime.Local || col.DateTimeMode == DataSetDateTime.Utc)
\r
1032 internal static object GetDefaultValueForType (Type type)
\r
1036 return DBNull.Value;
\r
1037 if (type.Namespace == "System.Data.SqlTypes" && type.Assembly == typeof (DataColumn).Assembly) {
\r
1038 // For SqlXxx types, set SqlXxx.Null instead of DBNull.Value.
\r
1039 if (type == typeof (SqlBinary))
\r
1040 return SqlBinary.Null;
\r
1041 if (type == typeof (SqlBoolean))
\r
1042 return SqlBoolean.Null;
\r
1043 if (type == typeof (SqlByte))
\r
1044 return SqlByte.Null;
\r
1045 if (type == typeof (SqlBytes))
\r
1046 return SqlBytes.Null;
\r
1047 if (type == typeof (SqlChars))
\r
1048 return SqlChars.Null;
\r
1049 if (type == typeof (SqlDateTime))
\r
1050 return SqlDateTime.Null;
\r
1051 if (type == typeof (SqlDecimal))
\r
1052 return SqlDecimal.Null;
\r
1053 if (type == typeof (SqlDouble))
\r
1054 return SqlDouble.Null;
\r
1055 if (type == typeof (SqlGuid))
\r
1056 return SqlGuid.Null;
\r
1057 if (type == typeof (SqlInt16))
\r
1058 return SqlInt16.Null;
\r
1059 if (type == typeof (SqlInt32))
\r
1060 return SqlInt32.Null;
\r
1061 if (type == typeof (SqlInt64))
\r
1062 return SqlInt64.Null;
\r
1063 if (type == typeof (SqlMoney))
\r
1064 return SqlMoney.Null;
\r
1065 if (type == typeof (SqlSingle))
\r
1066 return SqlSingle.Null;
\r
1067 if (type == typeof (SqlString))
\r
1068 return SqlString.Null;
\r
1069 if (type == typeof (SqlXml))
\r
1070 return SqlXml.Null;
\r
1073 return DBNull.Value;
\r
1076 #endregion // Methods
\r