-//
-// System.Data.DataColumn.cs
-//
-// Author:
-// Franklin Wise (gracenote@earthlink.net)
-// Christopher Podurgiel (cpodurgiel@msn.com)
-// Rodrigo Moya (rodrigo@ximian.com)
-// Daniel Morgan (danmorg@sc.rr.com)
-// Tim Coleman (tim@timcoleman.com)
-//
-// (C) Copyright 2002, Franklin Wise
-// (C) Chris Podurgiel
-// (C) Ximian, Inc 2002
-// Copyright (C) Tim Coleman, 2002
-// Copyright (C) Daniel Morgan, 2002, 2003
-//
-
-using System;
-using System.ComponentModel;
-using System.Reflection;
-
-namespace System.Data {
- internal delegate void DelegateColumnValueChange(DataColumn column, DataRow row, object proposedValue);
-
- /// <summary>
- /// Summary description for DataColumn.
- /// </summary>
-
- [DefaultMember ("Item")]
- [DefaultProperty ("ColumnName")]
- [DesignTimeVisible (false)]
- public class DataColumn : MarshalByValueComponent
- {
- #region Events
- [MonoTODO]
- //used for constraint validation
- //if an exception is fired during this event the change should be canceled
- internal event DelegateColumnValueChange ValidateColumnValueChange;
-
- //used for FK Constraint Cascading rules
- internal event DelegateColumnValueChange ColumnValueChanging;
- #endregion //Events
-
- #region Fields
-
- private bool _allowDBNull = true;
- private bool _autoIncrement = false;
- private long _autoIncrementSeed = 0;
- private long _autoIncrementStep = 1;
- private long _nextAutoIncrementValue = 0;
- private bool dataHasBeenSet = false;
- private string _caption = null;
- private MappingType _columnMapping = MappingType.Element;
- private string _columnName = null;
- private Type _dataType = Type.GetType ("System.String");
- private object _defaultValue = DBNull.Value;
- private string expression = "";
- private PropertyCollection _extendedProperties = new PropertyCollection ();
- private int maxLength = -1; //-1 represents no length limit
- private string nameSpace = "";
- private int _ordinal = -1; //-1 represents not part of a collection
- private string prefix = "";
- private bool readOnly = false;
- private DataTable _table = null;
- private bool unique = false;
-
- #endregion // Fields
-
- #region Constructors
-
- public DataColumn()
- {
- }
-
- //TODO: Ctor init vars directly
- public DataColumn(string columnName): this()
- {
- ColumnName = columnName;
- }
-
- public DataColumn(string columnName, Type dataType): this(columnName)
- {
- if(dataType == null) {
- throw new ArgumentNullException("dataType can't be null.");
- }
-
- DataType = dataType;
-
- }
-
- public DataColumn( string columnName, Type dataType,
- string expr): this(columnName, dataType)
- {
- Expression = expr;
- }
-
- public DataColumn(string columnName, Type dataType,
- string expr, MappingType type): this(columnName, dataType, expr)
- {
- ColumnMapping = type;
- }
- #endregion
-
- #region Properties
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates whether null values are allowed in this column.")]
- [DefaultValue (true)]
- public bool AllowDBNull
- {
- get {
- return _allowDBNull;
- }
- set {
- //TODO: If we are a part of the table and this value changes
- //we need to validate that all the existing values conform to the new setting
-
- if (true == value)
- {
- _allowDBNull = true;
- return;
- }
-
- //if Value == false case
- if (null != _table)
- {
- if (_table.Rows.Count > 0)
- {
- bool nullsFound = false;
- for(int r = 0; r < _table.Rows.Count; r++) {
- DataRow row = _table.Rows[r];
- if(row.IsNull(this)) {
- nullsFound = true;
- break;
- }
- }
-
- //TODO: Validate no null values exist
- //do we also check different versions of the row??
- }
- }
-
- _allowDBNull = value;
- }
- }
-
- /// <summary>
- /// Gets or sets a value indicating whether the column automatically increments the value of the column for new rows added to the table.
- /// </summary>
- /// <remarks>
- /// If the type of this column is not Int16, Int32, or Int64 when this property is set,
- /// the DataType property is coerced to Int32. An exception is generated if this is a computed column
- /// (that is, the Expression property is set.) The incremented value is used only if the row's value for this column,
- /// when added to the columns collection, is equal to the default value.
- /// </remarks>
- [DataCategory ("Data")]
- [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.")]
- [DefaultValue (false)]
- [RefreshProperties (RefreshProperties.All)]
- public bool AutoIncrement
- {
- get {
- return _autoIncrement;
- }
- set {
- if(value == true)
- {
- //Can't be true if this is a computed column
- if(!Expression.Equals(String.Empty))
- {
- throw new ArgumentException("Can not Auto Increment a computed column.");
- }
-
- //If the DataType of this Column isn't an Int
- //Make it an int
- TypeCode typeCode = Type.GetTypeCode(_dataType);
- if(typeCode != TypeCode.Int16 &&
- typeCode != TypeCode.Int32 &&
- typeCode != TypeCode.Int64)
- {
- _dataType = typeof(Int32);
- }
- }
- _autoIncrement = value;
- }
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the starting value for an AutoIncrement column.")]
- [DefaultValue (0)]
- public long AutoIncrementSeed
- {
- get {
- return _autoIncrementSeed;
- }
- set {
- _autoIncrementSeed = value;
- _nextAutoIncrementValue = _autoIncrementSeed;
- }
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the increment used by an AutoIncrement column.")]
- [DefaultValue (1)]
- public long AutoIncrementStep
- {
- get {
- return _autoIncrementStep;
- }
- set {
- _autoIncrementStep = value;
- }
- }
-
- internal void UpdateAutoIncrementValue (long value)
- {
- if(value > _nextAutoIncrementValue) {
- _nextAutoIncrementValue = value;
- AutoIncrementValue ();
- }
- }
-
- internal long AutoIncrementValue ()
- {
- long currentValue = _nextAutoIncrementValue;
- _nextAutoIncrementValue += AutoIncrementStep;
- return currentValue;
- }
-
- internal bool DataHasBeenSet {
- get {
- return dataHasBeenSet;
- }
- set {
- dataHasBeenSet = value;
- }
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the default user-interface caption for this column.")]
- public string Caption
- {
- get {
- if(_caption == null)
- return ColumnName;
- else
- return _caption;
- }
- set {
- _caption = value;
- }
- }
- [DataSysDescription ("Indicates how this column persists in XML: as an attribute, element, simple content node, or nothing.")]
- [DefaultValue (MappingType.Element)]
- public virtual MappingType ColumnMapping
- {
- get {
- return _columnMapping;
- }
- set {
- _columnMapping = value;
- }
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the name used to look up this column in the Columns collection of a DataTable.")]
- [RefreshProperties (RefreshProperties.All)]
- public string ColumnName
- {
- get {
- return "" + _columnName;
- }
- set {
- //Both are checked after the column is part of the collection
- //TODO: Check Name duplicate
- //TODO: check Name != null
- _columnName = value;
- }
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the type of data stored in this column.")]
- [DefaultValue (typeof (string))]
- [RefreshProperties (RefreshProperties.All)]
- public Type DataType
- {
- get {
- return _dataType;
- }
- set {
- // check if data already exists can we change the datatype
- if(DataHasBeenSet == true)
- throw new ArgumentException("The column already has data stored.");
-
- // we want to check that the datatype is supported?
- TypeCode typeCode = Type.GetTypeCode(value);
-
- //Check AutoIncrement status, make compatible datatype
- if(AutoIncrement == true) {
- if(typeCode != TypeCode.Int16 &&
- typeCode != TypeCode.Int32 &&
- typeCode != TypeCode.Int64)
- throw new ArgumentException("AutoIncrement is true, but the value is set to a type unsupported by AutoIncrement.");
- }
- _dataType = value;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <remarks>When AutoIncrement is set to true, there can be no default value.</remarks>
- /// <exception cref="System.InvalidCastException"></exception>
- /// <exception cref="System.ArgumentException"></exception>
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the default column value used when adding new rows to the table.")]
- public object DefaultValue
- {
- get {
- return _defaultValue;
- }
- set {
-
- //If autoIncrement == true throw
- if (AutoIncrement)
- {
- throw new ArgumentException("Can not set default value while" +
- " AutoIncrement is true on this column.");
- }
-
- //Will throw invalid cast exception
- //if value is not the correct type
- //FIXME: some types can be casted
- if (value.GetType() != _dataType)
- {
- throw new InvalidCastException("Default Value type is not compatible with" +
- " column type.");
- }
-
- _defaultValue = value;
- }
- }
-
- [MonoTODO]
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the value that this column computes for each row based on other columns instead of taking user input.")]
- [DefaultValue ("")]
- [RefreshProperties (RefreshProperties.All)]
- public string Expression
- {
- get {
- return expression;
- }
- set {
- //TODO: validation of the expression
- expression = value; //Check?
- }
- }
-
- [Browsable (false)]
- [DataCategory ("Data")]
- [DataSysDescription ("The collection that holds custom user information.")]
- public PropertyCollection ExtendedProperties
- {
- get {
- return _extendedProperties;
- }
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the maximum length of the value this column allows.")]
- [DefaultValue (-1)]
- public int MaxLength
- {
- get {
- //Default == -1 no max length
- return maxLength;
- }
- set {
- //only applies to string columns
- maxLength = value;
- }
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the XML uri for elements stored in this column.")]
- public string Namespace
- {
- get {
- return nameSpace;
- }
- set {
- nameSpace = value;
- }
- }
-
- //Need a good way to set the Ordinal when the column is added to a columnCollection.
- [Browsable (false)]
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the index of this column in the Columns collection.")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- public int Ordinal
- {
- get {
- //value is -1 if not part of a collection
- return _ordinal;
- }
- }
-
- internal void SetOrdinal(int ordinal)
- {
- _ordinal = ordinal;
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates the prefix used for this DataColumn in the xml representation.")]
- [DefaultValue ("")]
- public string Prefix
- {
- get {
- return prefix;
- }
- set {
- prefix = value;
- }
- }
-
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates whether this column allows changes once a row has been added to the table.")]
- [DefaultValue (false)]
- public bool ReadOnly
- {
- get {
- return readOnly;
- }
- set {
- readOnly = value;
- }
- }
-
- [Browsable (false)]
- [DataCategory ("Data")]
- [DataSysDescription ("Returns the DataTable to which this column belongs.")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- public DataTable Table
- {
- get {
- return _table;
- }
- }
-
- [MonoTODO]
- [DataCategory ("Data")]
- [DataSysDescription ("Indicates whether this column should restrict its values in the rows of the table to be unique.")]
- [DefaultValue (false)]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- public bool Unique
- {
- get {
- return unique;
- }
- set {
- //if Table == null then the UniqueConstraint is
- //created on addition to the collection
-
- //FIXME?: need to check if value is the same
- //because when calling "new UniqueConstraint"
- //the new object tries to set "column.Unique = True"
- //which creates an infinite loop.
- if(unique != value)
- {
- unique = value;
-
- if( value )
- {
- if( _table != null )
- {
- UniqueConstraint uc = new UniqueConstraint(this);
- _table.Constraints.Add(uc);
- }
- }
- else
- {
- if( _table != null )
- {
- //FIXME: Add code to remove constraint from DataTable
- throw new NotImplementedException ();
- }
- }
-
- }
- }
- }
-
- #endregion // Properties
-
- #region Methods
-
-/* ??
- [MonoTODO]
- protected internal void CheckNotAllowNull() {
- }
-
- [MonoTODO]
- protected void CheckUnique() {
- }
-*/
-
- [MonoTODO]
- internal void AssertCanAddToCollection()
- {
- //Check if Default Value is set and AutoInc is set
- }
-
- [MonoTODO]
- protected internal virtual void
- OnPropertyChanging (PropertyChangedEventArgs pcevent) {
- }
-
- [MonoTODO]
- protected internal void RaisePropertyChanging(string name) {
- }
-
- /// <summary>
- /// Gets the Expression of the column, if one exists.
- /// </summary>
- /// <returns>The Expression value, if the property is set;
- /// otherwise, the ColumnName property.</returns>
- [MonoTODO]
- public override string ToString()
- {
- if (expression != null)
- return expression;
-
- return ColumnName;
- }
-
- [MonoTODO]
- internal void SetTable(DataTable table) {
- _table = table;
- // this will get called by DataTable
- // and DataColumnCollection
- }
-
-
- // Returns true if all the same collumns are in columnSet and compareSet
- internal static bool AreColumnSetsTheSame(DataColumn[] columnSet, DataColumn[] compareSet)
- {
- if (null == columnSet && null == compareSet) return true;
- if (null == columnSet || null == compareSet) return false;
-
- if (columnSet.Length != compareSet.Length) return false;
-
- foreach (DataColumn col in columnSet)
- {
- bool matchFound = false;
- foreach (DataColumn compare in compareSet)
- {
- if (col == compare)
- {
- matchFound = true;
- }
- }
- if (! matchFound) return false;
- }
-
- return true;
- }
-
- #endregion // Methods
-
- }
-}
+//\r
+// System.Data.DataColumn.cs\r
+//\r
+// Author:\r
+// Franklin Wise (gracenote@earthlink.net)\r
+// Christopher Podurgiel (cpodurgiel@msn.com)\r
+// Rodrigo Moya (rodrigo@ximian.com)\r
+// Daniel Morgan (danmorg@sc.rr.com)\r
+// Tim Coleman (tim@timcoleman.com)\r
+//\r
+// (C) Copyright 2002, Franklin Wise\r
+// (C) Chris Podurgiel\r
+// (C) Ximian, Inc 2002\r
+// Copyright (C) Tim Coleman, 2002\r
+// Copyright (C) Daniel Morgan, 2002, 2003\r
+//\r
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
+using System;\r
+using System.ComponentModel;\r
+using System.Reflection;\r
+using System.Collections;\r
+using System.Data.Common;\r
+using System.Globalization;\r
+using Mono.Data.SqlExpressions;\r
+\r
+namespace System.Data {\r
+ internal delegate void DelegateColumnValueChange(DataColumn column, DataRow row, object proposedValue);\r
+ \r
+ /// <summary>\r
+ /// Summary description for DataColumn.\r
+ /// </summary>\r
+\r
+ [Editor]\r
+ [ToolboxItem (false)]\r
+ [DefaultProperty ("ColumnName")]\r
+ [DesignTimeVisible (false)]\r
+ public class DataColumn : MarshalByValueComponent\r
+ { \r
+ #region Events\r
+ [MonoTODO]\r
+ //used for constraint validation\r
+ //if an exception is fired during this event the change should be canceled\r
+ internal event DelegateColumnValueChange ValidateColumnValueChange;\r
+\r
+ //used for FK Constraint Cascading rules\r
+ internal event DelegateColumnValueChange ColumnValueChanging;\r
+ #endregion //Events\r
+ \r
+ #region Fields\r
+\r
+ private bool _allowDBNull = true;\r
+ private bool _autoIncrement;\r
+ private long _autoIncrementSeed;\r
+ private long _autoIncrementStep = 1;\r
+ private long _nextAutoIncrementValue;\r
+ private string _caption;\r
+ private MappingType _columnMapping;\r
+ private string _columnName = String.Empty;\r
+ private object _defaultValue = DBNull.Value;\r
+ private string _expression;\r
+ private IExpression _compiledExpression;\r
+ private PropertyCollection _extendedProperties = new PropertyCollection ();\r
+ private int _maxLength = -1; //-1 represents no length limit\r
+ private string _nameSpace;\r
+ private int _ordinal = -1; //-1 represents not part of a collection\r
+ private string _prefix = String.Empty;\r
+ private bool _readOnly;\r
+ private DataTable _table;\r
+ private bool _unique;\r
+ private AbstractDataContainer _dataContainer;\r
+\r
+ #endregion // Fields\r
+\r
+ #region Constructors\r
+\r
+ public DataColumn() : this(String.Empty, typeof (string), String.Empty, MappingType.Element)\r
+ {\r
+ }\r
+\r
+ //TODO: Ctor init vars directly\r
+ public DataColumn(string columnName): this(columnName, typeof (string), String.Empty, MappingType.Element)\r
+ {\r
+ }\r
+\r
+ public DataColumn(string columnName, Type dataType): this(columnName, dataType, String.Empty, MappingType.Element)\r
+ {\r
+ }\r
+\r
+ public DataColumn( string columnName, Type dataType, \r
+ string expr): this(columnName, dataType, expr, MappingType.Element)\r
+ {\r
+ }\r
+\r
+ public DataColumn(string columnName, Type dataType, \r
+ string expr, MappingType type)\r
+ {\r
+ ColumnName = (columnName == null ? String.Empty : columnName);\r
+ \r
+ if(dataType == null) {\r
+ throw new ArgumentNullException("dataType can't be null.");\r
+ }\r
+ \r
+ DataType = dataType;\r
+ Expression = expr == null ? String.Empty : expr;\r
+ ColumnMapping = type;\r
+ }\r
+ #endregion\r
+\r
+ #region Properties\r
+\r
+ internal object this[int index] {\r
+ get {\r
+ return DataContainer[index];\r
+ }\r
+ set {\r
+ if ( !(value == null && AutoIncrement) ) {\r
+ DataContainer[index] = value;\r
+ }\r
+\r
+ if ( AutoIncrement && !DataContainer.IsNull(index) ) {\r
+ long value64 = Convert.ToInt64(value);\r
+ UpdateAutoIncrementValue(value64);\r
+ }\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates whether null values are allowed in this column.")]\r
+ [DefaultValue (true)]\r
+ public bool AllowDBNull\r
+ {\r
+ get {\r
+ return _allowDBNull;\r
+ }\r
+ set {\r
+ //TODO: If we are a part of the table and this value changes\r
+ //we need to validate that all the existing values conform to the new setting\r
+\r
+ if (true == value)\r
+ {\r
+ _allowDBNull = true;\r
+ return;\r
+ }\r
+ \r
+ //if Value == false case\r
+ if (null != _table)\r
+ {\r
+ if (_table.Rows.Count > 0)\r
+ {\r
+ bool nullsFound = false;\r
+ for(int r = 0; r < _table.Rows.Count; r++) {\r
+ DataRow row = _table.Rows[r];\r
+ if(row.IsNull(this)) {\r
+ nullsFound = true;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if (nullsFound)\r
+ throw new DataException("Column '" + ColumnName + "' has null values in it.");\r
+ //TODO: Validate no null values exist\r
+ //do we also check different versions of the row??\r
+ }\r
+ }\r
+ \r
+ _allowDBNull = value;\r
+ }\r
+ }\r
+ \r
+ /// <summary>\r
+ /// Gets or sets a value indicating whether the column automatically increments the value of the column for new rows added to the table.\r
+ /// </summary>\r
+ /// <remarks>\r
+ /// If the type of this column is not Int16, Int32, or Int64 when this property is set, \r
+ /// the DataType property is coerced to Int32. An exception is generated if this is a computed column \r
+ /// (that is, the Expression property is set.) The incremented value is used only if the row's value for this column, \r
+ /// when added to the columns collection, is equal to the default value.\r
+ /// </remarks>\r
+ [DataCategory ("Data")]\r
+ [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
+ [DefaultValue (false)]\r
+ [RefreshProperties (RefreshProperties.All)]\r
+ public bool AutoIncrement\r
+ {\r
+ get {\r
+ return _autoIncrement;\r
+ }\r
+ set {\r
+ if(value == true)\r
+ {\r
+ //Can't be true if this is a computed column\r
+ if (Expression != string.Empty)\r
+ {\r
+ throw new ArgumentException("Can not Auto Increment a computed column."); \r
+ }\r
+\r
+ if ( DefaultValue != DBNull.Value ) {\r
+ throw new ArgumentException("Can not set AutoIncrement while" +\r
+ " default value exists for this column.");\r
+ }\r
+\r
+ if(!CanAutoIncrement(DataType))\r
+ {\r
+ DataType = typeof(Int32); \r
+ }\r
+\r
+ if (_table != null)\r
+ _table.Columns.UpdateAutoIncrement(this,true);\r
+ }\r
+ else\r
+ {\r
+ if (_table != null)\r
+ _table.Columns.UpdateAutoIncrement(this,false);\r
+ }\r
+ _autoIncrement = value;\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the starting value for an AutoIncrement column.")]\r
+ [DefaultValue (0)]\r
+ public long AutoIncrementSeed\r
+ {\r
+ get {\r
+ return _autoIncrementSeed;\r
+ }\r
+ set {\r
+ _autoIncrementSeed = value;\r
+ _nextAutoIncrementValue = _autoIncrementSeed;\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the increment used by an AutoIncrement column.")]\r
+ [DefaultValue (1)]\r
+ public long AutoIncrementStep\r
+ {\r
+ get {\r
+ return _autoIncrementStep;\r
+ }\r
+ set {\r
+ _autoIncrementStep = value;\r
+ }\r
+ }\r
+\r
+ internal void UpdateAutoIncrementValue(long value64)\r
+ {\r
+ if (_autoIncrementStep > 0 ) {\r
+ if (value64 >= _nextAutoIncrementValue) {\r
+ _nextAutoIncrementValue = value64;\r
+ AutoIncrementValue ();\r
+ }\r
+ }\r
+ else if (value64 <= _nextAutoIncrementValue) {\r
+ AutoIncrementValue ();\r
+ }\r
+ }\r
+\r
+ internal long AutoIncrementValue () \r
+ {\r
+ long currentValue = _nextAutoIncrementValue;\r
+ _nextAutoIncrementValue += AutoIncrementStep;\r
+ return currentValue;\r
+ }\r
+\r
+ internal long GetAutoIncrementValue ()\r
+ {\r
+ return _nextAutoIncrementValue;\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the default user-interface caption for this column.")]\r
+ public string Caption \r
+ {\r
+ get {\r
+ if(_caption == null)\r
+ return ColumnName;\r
+ else\r
+ return _caption;\r
+ }\r
+ set {\r
+ if (value == null)\r
+ value = String.Empty;\r
+ \r
+ _caption = value;\r
+ }\r
+ }\r
+ [DataSysDescription ("Indicates how this column persists in XML: as an attribute, element, simple content node, or nothing.")]\r
+ [DefaultValue (MappingType.Element)]\r
+ public virtual MappingType ColumnMapping\r
+ {\r
+ get {\r
+ return _columnMapping;\r
+ }\r
+ set {\r
+ _columnMapping = value;\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the name used to look up this column in the Columns collection of a DataTable.")]\r
+ [RefreshProperties (RefreshProperties.All)]\r
+ [DefaultValue ("")]\r
+ public string ColumnName\r
+ {\r
+ get {\r
+ return _columnName;\r
+ }\r
+ set {\r
+ if (value == null)\r
+ value = String.Empty;\r
+\r
+ CultureInfo info = Table != null ? Table.Locale : CultureInfo.CurrentCulture;\r
+ if (String.Compare(value, _columnName, true, info) != 0) {\r
+ if (Table != null) {\r
+ if (value.Length == 0)\r
+ throw new ArgumentException("ColumnName is required when it is part of a DataTable.");\r
+\r
+ Table.Columns.RegisterName(value, this);\r
+ if (_columnName.Length > 0)\r
+ Table.Columns.UnregisterName(_columnName);\r
+ }\r
+\r
+ RaisePropertyChanging("ColumnName");\r
+ _columnName = value;\r
+\r
+ if (Table != null)\r
+ Table.ResetPropertyDescriptorsCache();\r
+ }\r
+ else if (String.Compare(value, _columnName, false, info) != 0) {\r
+ RaisePropertyChanging("ColumnName");\r
+ _columnName = value;\r
+\r
+ if (Table != null)\r
+ Table.ResetPropertyDescriptorsCache();\r
+ }\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the type of data stored in this column.")]\r
+ [DefaultValue (typeof (string))]\r
+ [RefreshProperties (RefreshProperties.All)]\r
+ [TypeConverterAttribute (typeof (ColumnTypeConverter))] \r
+ public Type DataType\r
+ {\r
+ get {\r
+ return DataContainer.Type;\r
+ }\r
+ set {\r
+\r
+ if ( value == null ) \r
+ return;\r
+\r
+ if ( _dataContainer != null ) {\r
+ if ( value == _dataContainer.Type ) \r
+ return;\r
+\r
+ // check if data already exists can we change the datatype\r
+ if ( _dataContainer.Capacity > 0 )\r
+ throw new ArgumentException("The column already has data stored.");\r
+ }\r
+\r
+ if (null != GetParentRelation () || null != GetChildRelation ())\r
+ throw new InvalidConstraintException ("Cannot change datatype, " + \r
+ "when column is part of a relation");\r
+ \r
+ _dataContainer = AbstractDataContainer.CreateInstance(value, this);\r
+\r
+ //Check AutoIncrement status, make compatible datatype\r
+ if(AutoIncrement == true) {\r
+ // we want to check that the datatype is supported?\r
+ TypeCode typeCode = Type.GetTypeCode(value);\r
+ \r
+ if(typeCode != TypeCode.Int16 &&\r
+ typeCode != TypeCode.Int32 &&\r
+ typeCode != TypeCode.Int64) {\r
+ AutoIncrement = false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// \r
+ /// </summary>\r
+ /// <remarks>When AutoIncrement is set to true, there can be no default value.</remarks>\r
+ /// <exception cref="System.InvalidCastException"></exception>\r
+ /// <exception cref="System.ArgumentException"></exception>\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the default column value used when adding new rows to the table.")]\r
+ [TypeConverterAttribute (typeof (System.Data.DefaultValueTypeConverter))]\r
+ public object DefaultValue\r
+ {\r
+ get {\r
+ return _defaultValue;\r
+ }\r
+\r
+ set {\r
+ if (AutoIncrement) {\r
+ throw new ArgumentException("Can not set default value while" +\r
+ " AutoIncrement is true on this column.");\r
+ }\r
+\r
+ object tmpObj;\r
+ if (!this._defaultValue.Equals(value)) { \r
+ if (value == null) {\r
+ tmpObj = DBNull.Value;\r
+ }\r
+ else {\r
+ tmpObj = value;\r
+ }\r
+\r
+ if ((this.DataType != typeof (object))&& (tmpObj != DBNull.Value)) {\r
+ try {\r
+ //Casting to the new type\r
+ tmpObj= Convert.ChangeType(tmpObj,this.DataType);\r
+ }\r
+ catch (InvalidCastException) {\r
+ throw new InvalidCastException("Default Value type is not compatible with" + \r
+ " column type.");\r
+ }\r
+ }\r
+ _defaultValue = tmpObj;\r
+ }\r
+\r
+ // store default value in the table if already belongs to\r
+ if (Table != null && Table.DefaultValuesRowIndex != -1) {\r
+ DataContainer[Table.DefaultValuesRowIndex] = _defaultValue;\r
+ }\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the value that this column computes for each row based on other columns instead of taking user input.")]\r
+ [DefaultValue ("")]\r
+ [RefreshProperties (RefreshProperties.All)]\r
+ public string Expression\r
+ {\r
+ get {\r
+ return _expression;\r
+ }\r
+ set {\r
+ if (value == null)\r
+ value = String.Empty;\r
+ \r
+ if (value != String.Empty) \r
+ {\r
+\r
+ if (AutoIncrement || Unique)\r
+ throw new ArgumentException("Cannot create an expression on a column that has AutoIncrement or Unique.");\r
+\r
+ if (Table != null)\r
+ {\r
+ for (int i = 0; i < Table.Constraints.Count; i++)\r
+ {\r
+ if (Table.Constraints[i].IsColumnContained(this))\r
+ throw new ArgumentException(String.Format("Cannot set Expression property on column {0}, because it is a part of a constraint.", ColumnName));\r
+ }\r
+ }\r
+\r
+ Parser parser = new Parser ();\r
+ IExpression compiledExpression = parser.Compile (value);\r
+\r
+ if (Table != null)\r
+ {\r
+ if (compiledExpression.DependsOn(this))\r
+ throw new ArgumentException("Cannot set Expression property due to circular reference in the expression.");\r
+ }\r
+ \r
+ ReadOnly = true;\r
+ _compiledExpression = compiledExpression;\r
+ }\r
+ else\r
+ {\r
+ _compiledExpression = null;\r
+ if (Table != null)\r
+ {\r
+ int defaultValuesRowIndex = Table.DefaultValuesRowIndex;\r
+ if ( defaultValuesRowIndex != -1) \r
+ DataContainer.FillValues(defaultValuesRowIndex);\r
+ }\r
+ }\r
+ _expression = value; \r
+ }\r
+ }\r
+\r
+ internal IExpression CompiledExpression {\r
+ get { return _compiledExpression; }\r
+ }\r
+\r
+ [Browsable (false)]\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("The collection that holds custom user information.")]\r
+ public PropertyCollection ExtendedProperties\r
+ {\r
+ get {\r
+ return _extendedProperties;\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the maximum length of the value this column allows.")]\r
+ [DefaultValue (-1)]\r
+ public int MaxLength\r
+ {\r
+ get {\r
+ //Default == -1 no max length\r
+ return _maxLength;\r
+ }\r
+ set {\r
+ if (value >= 0 &&\r
+ _columnMapping == MappingType.SimpleContent)\r
+ throw new ArgumentException (String.Format ("Cannot set MaxLength property on '{0}' column which is mapped to SimpleContent.", ColumnName));\r
+ //only applies to string columns\r
+ _maxLength = value;\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the XML uri for elements stored in this column.")]\r
+ public string Namespace\r
+ {\r
+ get {\r
+ if (_nameSpace != null)\r
+ {\r
+ return _nameSpace;\r
+ }\r
+ if ((Table != null) && (_columnMapping != MappingType.Attribute))\r
+ {\r
+ return Table.Namespace;\r
+ }\r
+ return String.Empty;\r
+ }\r
+ set {\r
+ _nameSpace = value;\r
+ }\r
+ }\r
+\r
+ //Need a good way to set the Ordinal when the column is added to a columnCollection.\r
+ [Browsable (false)]\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the index of this column in the Columns collection.")]\r
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+ public int Ordinal\r
+ {\r
+ get {\r
+ //value is -1 if not part of a collection\r
+ return _ordinal;\r
+ }\r
+ }\r
+\r
+ internal void SetOrdinal(int ordinal)\r
+ {\r
+ _ordinal = ordinal;\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates the prefix used for this DataColumn in the xml representation.")]\r
+ [DefaultValue ("")]\r
+ public string Prefix\r
+ {\r
+ get {\r
+ return _prefix;\r
+ }\r
+ set {\r
+ if (value == null)\r
+ value = String.Empty;\r
+ _prefix = value;\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates whether this column allows changes once a row has been added to the table.")]\r
+ [DefaultValue (false)]\r
+ public bool ReadOnly\r
+ {\r
+ get {\r
+ return _readOnly;\r
+ }\r
+ set {\r
+ _readOnly = value;\r
+ }\r
+ }\r
+\r
+ [Browsable (false)]\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Returns the DataTable to which this column belongs.")]\r
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] \r
+ public DataTable Table\r
+ {\r
+ get {\r
+ return _table;\r
+ }\r
+ }\r
+\r
+ [DataCategory ("Data")]\r
+ [DataSysDescription ("Indicates whether this column should restrict its values in the rows of the table to be unique.")]\r
+ [DefaultValue (false)]\r
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+ public bool Unique \r
+ {\r
+ get {\r
+ return _unique;\r
+ }\r
+ set {\r
+ //NOTE: In .NET 1.1 the Unique property\r
+ //is left unchanged when it is added\r
+ //to a UniqueConstraint\r
+\r
+ if(_unique != value)\r
+ {\r
+ _unique = value;\r
+\r
+ if( value )\r
+ {\r
+ if (Expression != null && Expression != String.Empty)\r
+ throw new ArgumentException("Cannot change Unique property for the expression column.");\r
+ if( _table != null )\r
+ {\r
+ UniqueConstraint uc = new UniqueConstraint(this);\r
+ _table.Constraints.Add(uc);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if( _table != null )\r
+ {\r
+ ConstraintCollection cc = _table.Constraints;\r
+ //foreach (Constraint c in cc) \r
+ for (int i = 0; i < cc.Count; i++)\r
+ {\r
+ Constraint c = cc[i];\r
+ if (c is UniqueConstraint)\r
+ {\r
+ DataColumn[] cols = ((UniqueConstraint)c).Columns;\r
+ \r
+ if (cols.Length == 1 && cols[0] == this)\r
+ {\r
+ cc.Remove(c);\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+ }\r
+ }\r
+\r
+ internal AbstractDataContainer DataContainer {\r
+ get {\r
+ return _dataContainer;\r
+ }\r
+ }\r
+\r
+ internal static bool CanAutoIncrement(Type type) {\r
+ switch (Type.GetTypeCode(type)) {\r
+ case TypeCode.Int16:\r
+ case TypeCode.Int32:\r
+ case TypeCode.Int64:\r
+ case TypeCode.Decimal:\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ #endregion // Properties\r
+\r
+ #region Methods\r
+ \r
+/* ??\r
+ [MonoTODO]\r
+ protected internal void CheckNotAllowNull() {\r
+ }\r
+\r
+ [MonoTODO]\r
+ protected void CheckUnique() {\r
+ }\r
+*/\r
+ [MonoTODO]\r
+ internal DataColumn Clone() {\r
+ DataColumn copy = new DataColumn ();\r
+\r
+ // Copy all the properties of column\r
+ copy._allowDBNull = _allowDBNull;\r
+ copy._autoIncrement = _autoIncrement;\r
+ copy._autoIncrementSeed = _autoIncrementSeed;\r
+ copy._autoIncrementStep = _autoIncrementStep;\r
+ copy._caption = _caption;\r
+ copy._columnMapping = _columnMapping;\r
+ copy._columnName = _columnName;\r
+ //Copy.Container\r
+ copy.DataType = DataType;\r
+ copy._defaultValue = _defaultValue; \r
+ copy._expression = _expression;\r
+ //Copy.ExtendedProperties\r
+ copy._maxLength = _maxLength;\r
+ copy._nameSpace = _nameSpace;\r
+ copy._prefix = _prefix;\r
+ copy._readOnly = _readOnly;\r
+ //Copy.Site\r
+ //we do not copy the unique value - it will be copyied when copying the constraints.\r
+ //Copy.Unique = Column.Unique;\r
+ \r
+ return copy;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Sets unique true whithout creating Constraint\r
+ /// </summary>\r
+ internal void SetUnique() \r
+ {\r
+ _unique = true;\r
+ }\r
+\r
+ [MonoTODO]\r
+ internal void AssertCanAddToCollection()\r
+ {\r
+ //Check if Default Value is set and AutoInc is set\r
+ }\r
+\r
+ [MonoTODO]\r
+ protected internal void CheckNotAllowNull ()\r
+ {\r
+ throw new NotImplementedException ();\r
+ }\r
+\r
+ [MonoTODO]\r
+ protected void CheckUnique ()\r
+ {\r
+ throw new NotImplementedException ();\r
+ }\r
+\r
+ [MonoTODO]\r
+ protected internal virtual void \r
+ OnPropertyChanging (PropertyChangedEventArgs pcevent) {\r
+ }\r
+\r
+ [MonoTODO]\r
+ protected internal void RaisePropertyChanging(string name) {\r
+ }\r
+\r
+ /// <summary>\r
+ /// Gets the Expression of the column, if one exists.\r
+ /// </summary>\r
+ /// <returns>The Expression value, if the property is set; \r
+ /// otherwise, the ColumnName property.</returns>\r
+ public override string ToString()\r
+ {\r
+ if (_expression != string.Empty)\r
+ return ColumnName + " + " + _expression;\r
+ \r
+ return ColumnName;\r
+ }\r
+\r
+ internal void SetTable(DataTable table) {\r
+ if(_table!=null) { // serves as double check while adding to a table\r
+ throw new ArgumentException("The column already belongs to a different table");\r
+ }\r
+ _table = table;\r
+ // this will get called by DataTable\r
+ // and DataColumnCollection\r
+ if(_unique) {\r
+ // if the DataColumn is marked as Unique and then\r
+ // added to a DataTable , then a UniqueConstraint\r
+ // should be created\r
+ UniqueConstraint uc = new UniqueConstraint(this);\r
+ _table.Constraints.Add(uc);\r
+ }\r
+\r
+ // allocate space in the column data container \r
+ DataContainer.Capacity = _table.RecordCache.CurrentCapacity;\r
+ \r
+ int defaultValuesRowIndex = _table.DefaultValuesRowIndex;\r
+ if ( defaultValuesRowIndex != -1) {\r
+ // store default value in the table\r
+ DataContainer[defaultValuesRowIndex] = _defaultValue;\r
+ // Set all the values in data container to default\r
+ // it's cheaper that raise event on each row.\r
+ DataContainer.FillValues(defaultValuesRowIndex);\r
+ }\r
+ }\r
+ \r
+ // Returns true if all the same collumns are in columnSet and compareSet\r
+ internal static bool AreColumnSetsTheSame(DataColumn[] columnSet, DataColumn[] compareSet)\r
+ {\r
+ if (null == columnSet && null == compareSet) {\r
+ return true;\r
+ }\r
+\r
+ if (null == columnSet || null == compareSet) {\r
+ return false;\r
+ }\r
+\r
+ if (columnSet.Length != compareSet.Length) { \r
+ return false;\r
+ }\r
+ \r
+ foreach (DataColumn col in columnSet) {\r
+ bool matchFound = false;\r
+ foreach (DataColumn compare in compareSet) {\r
+ if (col == compare) {\r
+ matchFound = true; \r
+ }\r
+ }\r
+ if (! matchFound) {\r
+ return false;\r
+ }\r
+ } \r
+ return true;\r
+ }\r
+\r
+ \r
+ internal int CompareValues (int index1, int index2)\r
+ {\r
+ return DataContainer.CompareValues(index1, index2);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Returns the data relation, which contains this column.\r
+ /// This searches in current table's parent relations.\r
+ /// <summary>\r
+ /// <returns>\r
+ /// DataRelation if found otherwise null.\r
+ /// </returns>\r
+ private DataRelation GetParentRelation ()\r
+ {\r
+ if (_table == null)\r
+ return null;\r
+ foreach (DataRelation rel in _table.ParentRelations)\r
+ if (rel.Contains (this))\r
+ return rel;\r
+ return null;\r
+ }\r
+ \r
+\r
+ /// <summary>\r
+ /// Returns the data relation, which contains this column.\r
+ /// This searches in current table's child relations.\r
+ /// <summary>\r
+ /// <returns>\r
+ /// DataRelation if found otherwise null.\r
+ /// </returns>\r
+ private DataRelation GetChildRelation ()\r
+ {\r
+ if (_table == null)\r
+ return null;\r
+ foreach (DataRelation rel in _table.ChildRelations)\r
+ if (rel.Contains (this))\r
+ return rel;\r
+ return null;\r
+ }\r
+ \r
+\r
+ #endregion // Methods\r
+\r
+ }\r
+}\r