New tests.
[mono.git] / mcs / class / System.Data / System.Data / DataColumn.cs
index d3bf788a47accb80db98d3452c0073aa0cca9e02..f5d84c562206660cb3fd31da5f5c509a2422bf12 100644 (file)
 // 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
+//\r
 // The above copyright notice and this permission notice shall be\r
 // included in all copies or substantial portions of the Software.\r
-// \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
@@ -43,12 +43,13 @@ using System.ComponentModel;
 using System.Reflection;\r
 using System.Collections;\r
 using System.Data.Common;\r
+using System.Data.SqlTypes;\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
+       internal delegate void DelegateColumnValueChange (DataColumn column, DataRow row, object proposedValue);\r
+\r
        /// <summary>\r
        /// Summary description for DataColumn.\r
        /// </summary>\r
@@ -58,20 +59,27 @@ namespace System.Data {
        [ToolboxItem (false)]\r
        [DefaultProperty ("ColumnName")]\r
        [DesignTimeVisible (false)]\r
-       public class DataColumn : MarshalByValueComponent\r
-       {               \r
-               #region Events\r
-               [MonoTODO]\r
+       public class DataColumn : MarshalByValueComponent {\r
+#region Events\r
+               EventHandlerList _eventHandlers = new EventHandlerList ();\r
+\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
+               //[MonoTODO]\r
+               //internal event DelegateColumnValueChange ValidateColumnValueChange;\r
 \r
                //used for FK Constraint Cascading rules\r
-               internal event DelegateColumnValueChange ColumnValueChanging;\r
+               //[MonoTODO]\r
+               //internal event DelegateColumnValueChange ColumnValueChanging;\r
+\r
+               static readonly object _propertyChangedKey = new object ();\r
+               internal event PropertyChangedEventHandler PropertyChanged {\r
+                       add { _eventHandlers.AddHandler (_propertyChangedKey, value); }\r
+                       remove { _eventHandlers.RemoveHandler (_propertyChangedKey, value); }\r
+               }\r
 \r
-               internal event PropertyChangedEventHandler PropertyChanged;\r
                #endregion //Events\r
-               \r
+\r
                #region Fields\r
 \r
                private bool _allowDBNull = true;\r
@@ -82,7 +90,7 @@ namespace System.Data {
                private string _caption;\r
                private MappingType _columnMapping;\r
                private string _columnName = String.Empty;\r
-               private object _defaultValue = DBNull.Value;\r
+               private object _defaultValue = GetDefaultValueForType (null);\r
                private string _expression;\r
                private IExpression _compiledExpression;\r
                private PropertyCollection _extendedProperties = new PropertyCollection ();\r
@@ -93,39 +101,40 @@ namespace System.Data {
                private bool _readOnly;\r
                private DataTable _table;\r
                private bool _unique;\r
-               private AbstractDataContainer _dataContainer;\r
+               private DataContainer _dataContainer;\r
 \r
                #endregion // Fields\r
 \r
                #region Constructors\r
 \r
-               public DataColumn() : this(String.Empty, typeof (string), String.Empty, MappingType.Element)\r
+               public DataColumn ()\r
+                       : 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
+               public DataColumn (string columnName)\r
+                       : 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
+               public DataColumn (string columnName, Type dataType)\r
+                       : 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
+               public DataColumn (string columnName, Type dataType, string expr)\r
+                       : this (columnName, dataType, expr, MappingType.Element)\r
                {\r
                }\r
 \r
-               public DataColumn(string columnName, Type dataType, \r
-                       string expr, MappingType type)\r
+               public DataColumn (string columnName, Type dataType, 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
+                       ColumnName = columnName == null ? String.Empty : columnName;\r
+\r
+                       if (dataType == null)\r
+                               throw new ArgumentNullException ("dataType");\r
+\r
                        DataType = dataType;\r
                        Expression = expr == null ? String.Empty : expr;\r
                        ColumnMapping = type;\r
@@ -134,25 +143,24 @@ namespace System.Data {
 \r
                #region Properties\r
 \r
-               internal object this[int index] {\r
-                       get {\r
-                               return DataContainer[index];\r
-                       }\r
+               internal object this [int index] {\r
+                       get { return DataContainer [index]; }\r
                        set {\r
-                               if ( !(value == null && AutoIncrement) ) {\r
+                               if (!(value == null && AutoIncrement)) {\r
                                        try {\r
-                                               DataContainer[index] = value;\r
-                                       }\r
-                                       catch(Exception e) {\r
-                                               throw new ArgumentException(e.Message +\r
-                                                       String.Format("Couldn't store <{0}> in {1} Column.  Expected type is {2}.",\r
-                                                       value, ColumnName, DataType.Name), e);\r
+                                               DataContainer [index] = value;\r
+                                       } catch(Exception e) {\r
+                                               throw new ArgumentException (\r
+                                                       String.Format (\r
+                                                               "{0}. Couldn't store <{1}> in Column named '{2}'. Expected type is {3}.",\r
+                                                               e.Message, value, ColumnName, DataType.Name),\r
+                                                       e);\r
                                        }\r
                                }\r
 \r
-                               if ( AutoIncrement && !DataContainer.IsNull(index) ) {\r
-                                       long value64 = Convert.ToInt64(value);\r
-                                       UpdateAutoIncrementValue(value64);\r
+                               if (AutoIncrement && !DataContainer.IsNull (index)) {\r
+                                       long value64 = Convert.ToInt64 (value);\r
+                                       UpdateAutoIncrementValue (value64);\r
                                }\r
                        }\r
                }\r
@@ -166,11 +174,13 @@ namespace System.Data {
                        set {\r
                                if (DataType != typeof (DateTime))\r
                                        throw new InvalidOperationException ("The DateTimeMode can be set only on DataColumns of type DateTime.");\r
-                               \r
+\r
                                if (!Enum.IsDefined (typeof (DataSetDateTime), value))\r
-                                       throw new InvalidEnumArgumentException ("The DataSetDateTime enumeration value, " + \r
-                                                       (int)value + ", is invalid.");\r
-                                               \r
+                                       throw new InvalidEnumArgumentException (\r
+                                               string.Format (\r
+                                                       CultureInfo.InvariantCulture, "The {0} enumeration value, {1}, is invalid",\r
+                                                       typeof (DataSetDateTime).Name, value));\r
+\r
                                if (_datetimeMode == value)\r
                                        return;\r
                                if (_table == null || _table.Rows.Count == 0) {\r
@@ -183,9 +193,9 @@ namespace System.Data {
                                        return;\r
                                }\r
 \r
-                               throw new InvalidOperationException ( String.Format (\r
-                                                                       "Cannot change DateTimeMode from '{0}' to '{1}' " +\r
-                                                                       "once the table has data.",_datetimeMode, value));\r
+                               throw new InvalidOperationException (\r
+                                       String.Format ("Cannot change DateTimeMode from '{0}' to '{1}' once the table has data.",\r
+                                                      _datetimeMode, value));\r
                        }\r
                }\r
 #endif\r
@@ -195,53 +205,31 @@ namespace System.Data {
                [DataSysDescription ("Indicates whether null values are allowed in this column.")]\r
 #endif\r
                [DefaultValue (true)]\r
-               public bool AllowDBNull\r
-               {\r
-                       get {\r
-                               return _allowDBNull;\r
-                       }\r
+               public bool AllowDBNull {\r
+                       get { return _allowDBNull; }\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
+                               if (!value && null != _table) {\r
+                                       for (int r = 0; r < _table.Rows.Count; r++) {\r
+                                               DataRow row = _table.Rows [r];\r
+                                               DataRowVersion version = row.HasVersion (DataRowVersion.Default) ?\r
+                                                       DataRowVersion.Default : DataRowVersion.Original;\r
+                                               if (row.IsNull (this, version))\r
+                                                       throw new DataException ("Column '" + ColumnName + "' has null values in it.");\r
+                                               //TODO: do we also check different versions of the row??\r
                                        }\r
                                }\r
-                                       \r
+\r
                                _allowDBNull = value;\r
                        }\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
+               ///             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
@@ -250,38 +238,23 @@ namespace System.Data {
 #endif\r
                [DefaultValue (false)]\r
                [RefreshProperties (RefreshProperties.All)]\r
-               public bool AutoIncrement\r
-               {\r
-                       get {\r
-                               return _autoIncrement;\r
-                       }\r
+               public bool AutoIncrement {\r
+                       get { return _autoIncrement; }\r
                        set {\r
-                               if(value == true)\r
-                               {\r
+                               if (value) {\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
+                                               throw new ArgumentException ("Can not Auto Increment a computed column.");\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
+                                       if (DefaultValue != DBNull.Value)\r
+                                               throw new ArgumentException ("Can not set AutoIncrement while default value exists for this column.");\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
+                                       if (!CanAutoIncrement (DataType))\r
+                                               DataType = typeof (Int32);\r
                                }\r
+\r
+                               if (_table != null)\r
+                                       _table.Columns.UpdateAutoIncrement (this, value);\r
                                _autoIncrement = value;\r
                        }\r
                }\r
@@ -291,11 +264,8 @@ namespace System.Data {
                [DataSysDescription ("Indicates the starting value for an AutoIncrement column.")]\r
 #endif\r
                [DefaultValue (0)]\r
-               public long AutoIncrementSeed\r
-               {\r
-                       get {\r
-                               return _autoIncrementSeed;\r
-                       }\r
+               public long AutoIncrementSeed {\r
+                       get { return _autoIncrementSeed; }\r
                        set {\r
                                _autoIncrementSeed = value;\r
                                _nextAutoIncrementValue = _autoIncrementSeed;\r
@@ -307,30 +277,24 @@ namespace System.Data {
                [DataSysDescription ("Indicates the increment used by an AutoIncrement column.")]\r
 #endif\r
                [DefaultValue (1)]\r
-               public long AutoIncrementStep\r
-               {\r
-                       get {\r
-                               return _autoIncrementStep;\r
-                       }\r
-                       set {\r
-                               _autoIncrementStep = value;\r
-                       }\r
+               public long AutoIncrementStep {\r
+                       get { return _autoIncrementStep; }\r
+                       set { _autoIncrementStep = value; }\r
                }\r
 \r
-               internal void UpdateAutoIncrementValue(long value64)\r
+               internal void UpdateAutoIncrementValue (long value64)\r
                {\r
-                       if (_autoIncrementStep > 0 ) {\r
+                       if (_autoIncrementStep > 0) {\r
                                if (value64 >= _nextAutoIncrementValue) {\r
                                        _nextAutoIncrementValue = value64;\r
                                        AutoIncrementValue ();\r
                                }\r
-                       }\r
-                       else if (value64 <= _nextAutoIncrementValue) {\r
+                       } else if (value64 <= _nextAutoIncrementValue) {\r
                                AutoIncrementValue ();\r
                        }\r
                }\r
 \r
-               internal long AutoIncrementValue () \r
+               internal long AutoIncrementValue ()\r
                {\r
                        long currentValue = _nextAutoIncrementValue;\r
                        _nextAutoIncrementValue += AutoIncrementStep;\r
@@ -342,45 +306,30 @@ namespace System.Data {
                        return _nextAutoIncrementValue;\r
                }\r
 \r
-               internal void SetDefaultValue(int index) {\r
+               internal void SetDefaultValue (int index)\r
+               {\r
                        if (AutoIncrement)\r
-                               this[index] = _nextAutoIncrementValue;\r
+                               this [index] = _nextAutoIncrementValue;\r
                        else\r
-                               DataContainer.CopyValue(Table.DefaultValuesRowIndex, index);\r
+                               DataContainer.CopyValue (Table.DefaultValuesRowIndex, index);\r
                }\r
 \r
                [DataCategory ("Data")]\r
 #if !NET_2_0\r
                [DataSysDescription ("Indicates the default user-interface caption for this column.")]\r
 #endif\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
+               public string Caption {\r
+                       get { return _caption == null ? ColumnName : _caption; }\r
+                       set { _caption = value == null ? String.Empty : value; }\r
                }\r
 \r
 #if !NET_2_0\r
                [DataSysDescription ("Indicates how this column persists in XML: as an attribute, element, simple content node, or nothing.")]\r
 #endif\r
                [DefaultValue (MappingType.Element)]\r
-               public virtual MappingType ColumnMapping\r
-               {\r
-                       get {\r
-                               return _columnMapping;\r
-                       }\r
-                       set {\r
-                               _columnMapping = value;\r
-                       }\r
+               public virtual MappingType ColumnMapping {\r
+                       get { return _columnMapping; }\r
+                       set { _columnMapping = value; }\r
                }\r
 \r
                [DataCategory ("Data")]\r
@@ -389,38 +338,34 @@ namespace System.Data {
 #endif\r
                [RefreshProperties (RefreshProperties.All)]\r
                [DefaultValue ("")]\r
-               public string ColumnName\r
-               {\r
-                       get {\r
-                               return _columnName;\r
-                       }\r
+               public string ColumnName {\r
+                       get { return _columnName; }\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 (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
+                                                       throw new ArgumentException ("ColumnName is required when it is part of a DataTable.");\r
 \r
-                                               Table.Columns.RegisterName(value, this);\r
+                                               Table.Columns.RegisterName (value, this);\r
                                                if (_columnName.Length > 0)\r
-                                                       Table.Columns.UnregisterName(_columnName);\r
+                                                       Table.Columns.UnregisterName (_columnName);\r
                                        }\r
 \r
-                                       RaisePropertyChanging("ColumnName");\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
+                                               Table.ResetPropertyDescriptorsCache ();\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
+                                               Table.ResetPropertyDescriptorsCache ();\r
                                }\r
                        }\r
                }\r
@@ -431,52 +376,49 @@ namespace System.Data {
 #endif\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
+               [TypeConverterAttribute (typeof (ColumnTypeConverter))]\r
+               public Type DataType {\r
+                       get { return DataContainer.Type; }\r
                        set {\r
+                               if (value == null)\r
+                                       return;\r
 \r
-                                if ( value == null ) \r
-                                        return;\r
-\r
-                               if ( _dataContainer != null ) {\r
-                                       if ( value == _dataContainer.Type ) \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
+                                       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
+                               if (null != GetParentRelation () || null != GetChildRelation ())\r
+                                       throw new InvalidConstraintException ("Cannot change datatype when column is part of a relation");\r
+\r
+                               Type prevType = _dataContainer != null ? _dataContainer.Type : null; // current\r
+\r
 #if NET_2_0\r
                                if (_dataContainer != null && _dataContainer.Type == typeof (DateTime))\r
                                        _datetimeMode = DataSetDateTime.UnspecifiedLocal;\r
 #endif\r
-                                _dataContainer = AbstractDataContainer.CreateInstance(value, this);\r
+                               _dataContainer = DataContainer.Create (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
+                                       // we want to check that the datatype is supported?                                     \r
+                                       if (!CanAutoIncrement (value))\r
                                                AutoIncrement = false;\r
-                                       }\r
                                }\r
+\r
+                               if (DefaultValue != GetDefaultValueForType (prevType))\r
+                                       SetDefaultValue (DefaultValue, true);\r
+                               else\r
+                                       _defaultValue = GetDefaultValueForType (DataType);\r
                        }\r
                }\r
 \r
                /// <summary>\r
-               /// \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
@@ -486,45 +428,39 @@ namespace System.Data {
                [DataSysDescription ("Indicates the default column value used when adding new rows to the table.")]\r
 #endif\r
                [TypeConverterAttribute (typeof (System.Data.DefaultValueTypeConverter))]\r
-               public object DefaultValue\r
-               {\r
-                       get {\r
-                               return _defaultValue;\r
-                       }\r
+               public object DefaultValue {\r
+                       get { return _defaultValue; }\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
+                               if (AutoIncrement)\r
+                                       throw new ArgumentException ("Can not set default value while AutoIncrement is true on this column.");\r
+                               SetDefaultValue (value, false);\r
+                       }\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
+               void SetDefaultValue (object value, bool forcedTypeCheck)\r
+               {\r
+                       if (forcedTypeCheck || !this._defaultValue.Equals (value)) {\r
+                               if (value == null || value == DBNull.Value)\r
+                                       _defaultValue = GetDefaultValueForType (DataType);\r
+                               else if (DataType.IsInstanceOfType (value))\r
+                                       _defaultValue = value;\r
+                               else\r
+                                       try {\r
+                                               _defaultValue = Convert.ChangeType (value, DataType);\r
+                                       } catch (InvalidCastException) {\r
+                                               string msg = String.Format ("Default Value of type '{0}' is not compatible with column type '{1}'", value.GetType (), DataType);\r
+#if NET_2_0\r
+                                               throw new DataException (msg);\r
+#else\r
+                                               throw new ArgumentException (msg);\r
+#endif\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
+                       // 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
                [DataCategory ("Data")]\r
@@ -533,56 +469,49 @@ namespace System.Data {
 #endif\r
                [DefaultValue ("")]\r
                [RefreshProperties (RefreshProperties.All)]\r
-               public string Expression\r
-               {\r
-                       get {\r
-                               return _expression;\r
-                       }\r
+               public string Expression {\r
+                       get { return _expression; }\r
                        set {\r
                                if (value == null)\r
                                        value = String.Empty;\r
-                                       \r
-                               if (value != String.Empty) \r
-                               {\r
 \r
+                               if (value != String.Empty) {\r
                                        if (AutoIncrement || Unique)\r
-                                               throw new ArgumentException("Cannot create an expression on a column that has AutoIncrement or 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
+                                       if (Table != null) {\r
+                                               for (int i = 0; i < Table.Constraints.Count; i++) {\r
+                                                       if (Table.Constraints [i].IsColumnContained (this))\r
+                                                               throw new ArgumentException (\r
+                                                                       String.Format (\r
+                                                                               "Cannot set Expression property on column {0}, because it is a part of a constraint.",\r
+                                                                               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
-                                               // Check if expression is ok \r
+                                       if (Table != null) {\r
+                                               if (compiledExpression.DependsOn (this))\r
+                                                       throw new ArgumentException ("Cannot set Expression property due to circular reference in the expression.");\r
+                                               // Check if expression is ok\r
                                                if (Table.Rows.Count == 0)\r
-                                                       compiledExpression.Eval (Table.NewRow());\r
+                                                       compiledExpression.Eval (Table.NewRow ());\r
                                                else\r
-                                                       compiledExpression.Eval (Table.Rows[0]);\r
+                                                       compiledExpression.Eval (Table.Rows [0]);\r
                                        }\r
                                        ReadOnly = true;\r
                                        _compiledExpression = compiledExpression;\r
-                               }\r
-                               else\r
-                               {\r
+                               } else {\r
                                        _compiledExpression = null;\r
                                        if (Table != null) {\r
                                                int defaultValuesRowIndex = Table.DefaultValuesRowIndex;\r
-                                               if ( defaultValuesRowIndex != -1) \r
-                                                       DataContainer.FillValues(defaultValuesRowIndex);\r
+                                               if (defaultValuesRowIndex != -1)\r
+                                                       DataContainer.FillValues (defaultValuesRowIndex);\r
                                        }\r
                                }\r
-                               _expression = value;  \r
+                               _expression = value;\r
                        }\r
                }\r
 \r
@@ -595,11 +524,8 @@ namespace System.Data {
 #if !NET_2_0\r
                [DataSysDescription ("The collection that holds custom user information.")]\r
 #endif\r
-               public PropertyCollection ExtendedProperties\r
-               {\r
-                       get {\r
-                               return _extendedProperties;\r
-                       }\r
+               public PropertyCollection ExtendedProperties {\r
+                       get { return _extendedProperties; }\r
 #if NET_2_0\r
                        internal set { _extendedProperties = value; }\r
 #endif\r
@@ -609,17 +535,15 @@ namespace System.Data {
 #if !NET_2_0\r
                [DataSysDescription ("Indicates the maximum length of the value this column allows. ")]\r
 #endif\r
-               [DefaultValue (-1)]\r
-               public int MaxLength\r
-               {\r
-                       get {\r
-                               //Default == -1 no max length\r
-                               return _maxLength;\r
-                       }\r
+               [DefaultValue (-1)] //Default == -1 no max length\r
+               public int MaxLength {\r
+                       get { return _maxLength; }\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
+                               if (value >= 0 && _columnMapping == MappingType.SimpleContent)\r
+                                       throw new ArgumentException (\r
+                                               String.Format (\r
+                                                       "Cannot set MaxLength property on '{0}' column which is mapped to SimpleContent.",\r
+                                                       ColumnName));\r
                                //only applies to string columns\r
                                _maxLength = value;\r
                        }\r
@@ -629,22 +553,15 @@ namespace System.Data {
 #if !NET_2_0\r
                [DataSysDescription ("Indicates the XML uri for elements or attributes stored in this column.")]\r
 #endif\r
-               public string Namespace\r
-               {\r
+               public string Namespace {\r
                        get {\r
                                if (_nameSpace != null)\r
-                               {\r
                                        return _nameSpace;\r
-                               }\r
-                               if ((Table != null) && (_columnMapping != MappingType.Attribute))\r
-                               {\r
+                               if (Table != null && _columnMapping != MappingType.Attribute)\r
                                        return Table.Namespace;\r
-                               }\r
                                return String.Empty;\r
                        }\r
-                       set {\r
-                               _nameSpace = value;\r
-                       }\r
+                       set { _nameSpace = value; }\r
                }\r
 \r
                //Need a good way to set the Ordinal when the column is added to a columnCollection.\r
@@ -657,7 +574,7 @@ namespace System.Data {
                public int Ordinal {\r
                        get { return _ordinal; }\r
 #if NET_2_0\r
-                       internal  set { _ordinal = value; }\r
+                       internal set { _ordinal = value; }\r
 #endif\r
                }\r
 \r
@@ -681,16 +598,9 @@ namespace System.Data {
                [DataSysDescription ("Indicates the Prefix used for this DataColumn in xml representation.")]\r
 #endif\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
+               public string Prefix {\r
+                       get { return _prefix; }\r
+                       set { _prefix = value == null ? String.Empty : value; }\r
                }\r
 \r
                [DataCategory ("Data")]\r
@@ -698,14 +608,9 @@ namespace System.Data {
                [DataSysDescription ("Indicates whether this column allows changes once a row has been added to the table.")]\r
 #endif\r
                [DefaultValue (false)]\r
-               public bool ReadOnly\r
-               {\r
-                       get {\r
-                               return _readOnly;\r
-                       }\r
-                       set {\r
-                               _readOnly = value;\r
-                       }\r
+               public bool ReadOnly {\r
+                       get { return _readOnly; }\r
+                       set { _readOnly = value; }\r
                }\r
 \r
                [Browsable (false)]\r
@@ -713,12 +618,12 @@ namespace System.Data {
 #if !NET_2_0\r
                [DataSysDescription ("Returns the DataTable to which this column belongs.")]\r
 #endif\r
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]      \r
-               public DataTable Table\r
-               {\r
-                       get {\r
-                               return _table;\r
-                       }\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public DataTable Table {\r
+                       get { return _table; }\r
+#if NET_2_0\r
+                       internal set { _table = value; }\r
+#endif\r
                }\r
 \r
                [DataCategory ("Data")]\r
@@ -727,13 +632,9 @@ namespace System.Data {
 #endif\r
                [DefaultValue (false)]\r
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
-                public bool Unique \r
-               {\r
-                       get {\r
-                               return _unique;\r
-                       }\r
+               public bool Unique {\r
+                       get { return _unique; }\r
                        set {\r
-\r
                                if (_unique == value)\r
                                        return;\r
 \r
@@ -747,13 +648,13 @@ namespace System.Data {
                                try {\r
                                        if (value) {\r
                                                if (Expression != null && Expression != String.Empty)\r
-                                                       throw new ArgumentException("Cannot change Unique property for the expression column.");\r
+                                                       throw new ArgumentException ("Cannot change Unique property for the expression column.");\r
 \r
-                                               _table.Constraints.Add(null, this, false);\r
+                                               _table.Constraints.Add (null, this, false);\r
                                        } else {\r
 \r
-                                               UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet (_table.Constraints,\r
-                                                                                               new DataColumn[] {this});\r
+                                               UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet (\r
+                                                       _table.Constraints, new DataColumn[] {this});\r
                                                _table.Constraints.Remove (uc);\r
                                        }\r
                                } catch (Exception e) {\r
@@ -763,14 +664,13 @@ namespace System.Data {
                        }\r
                }\r
 \r
-               internal AbstractDataContainer DataContainer {\r
-                       get {\r
-                               return _dataContainer;\r
-                       }\r
+               internal DataContainer DataContainer {\r
+                       get { return _dataContainer; }\r
                }\r
 \r
-               internal static bool CanAutoIncrement(Type type) {\r
-                       switch (Type.GetTypeCode(type)) {\r
+               internal static bool CanAutoIncrement (Type type)\r
+               {\r
+                       switch (Type.GetTypeCode (type)) {\r
                                case TypeCode.Int16:\r
                                case TypeCode.Int32:\r
                                case TypeCode.Int64:\r
@@ -784,18 +684,10 @@ namespace System.Data {
                #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
+               internal DataColumn Clone ()\r
+               {\r
                        DataColumn copy = new DataColumn ();\r
 \r
                        // Copy all the properties of column\r
@@ -808,8 +700,9 @@ namespace System.Data {
                        copy._columnName = _columnName;\r
                        //Copy.Container\r
                        copy.DataType = DataType;\r
-                       copy._defaultValue = _defaultValue;                     \r
-                       copy._expression = _expression;\r
+                       copy._defaultValue = _defaultValue;\r
+                       // Use the property to set the expression as it updates compiledExpression, if any.\r
+                       copy.Expression = _expression;\r
                        //Copy.ExtendedProperties\r
                        copy._maxLength = _maxLength;\r
                        copy._nameSpace = _nameSpace;\r
@@ -822,20 +715,21 @@ namespace System.Data {
                        if (DataType == typeof (DateTime))\r
                                copy.DateTimeMode = _datetimeMode;\r
 #endif\r
-                       \r
+                       copy._extendedProperties = _extendedProperties;\r
+\r
                        return copy;\r
                }\r
 \r
                /// <summary>\r
                ///  Sets unique true whithout creating Constraint\r
                /// </summary>\r
-               internal void SetUnique() \r
+               internal void SetUnique ()\r
                {\r
                        _unique = true;\r
                }\r
 \r
                [MonoTODO]\r
-               internal void AssertCanAddToCollection()\r
+               internal void AssertCanAddToCollection ()\r
                {\r
                        //Check if Default Value is set and AutoInc is set\r
                }\r
@@ -852,13 +746,17 @@ namespace System.Data {
                        throw new NotImplementedException ();\r
                }\r
 \r
-               protected internal virtual void \r
-               OnPropertyChanging (PropertyChangedEventArgs pcevent) {\r
-                       if (PropertyChanged != null)\r
-                               PropertyChanged (this, pcevent);\r
+               protected internal virtual void\r
+               OnPropertyChanging (PropertyChangedEventArgs pcevent)\r
+               {\r
+                       PropertyChangedEventHandler eh = _eventHandlers [_propertyChangedKey] as PropertyChangedEventHandler;\r
+\r
+                       if (eh != null)\r
+                               eh (this, pcevent);\r
                }\r
 \r
-               protected internal void RaisePropertyChanging(string name) {\r
+               protected internal void RaisePropertyChanging (string name)\r
+               {\r
                        PropertyChangedEventArgs e = new PropertyChangedEventArgs (name);\r
                        OnPropertyChanging (e);\r
                }\r
@@ -866,114 +764,109 @@ namespace System.Data {
                /// <summary>\r
                /// Gets the Expression of the column, if one exists.\r
                /// </summary>\r
-               /// <returns>The Expression value, if the property is set; \r
+               /// <returns>The Expression value, if the property is set;\r
                /// otherwise, the ColumnName property.</returns>\r
-               public override string ToString()\r
+               public override string ToString ()\r
                {\r
                        if (_expression != string.Empty)\r
                                return ColumnName + " + " + _expression;\r
-                       \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
+               internal void SetTable (DataTable table)\r
+               {\r
+                       if(_table != null)\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
+\r
                        int defaultValuesRowIndex = _table.DefaultValuesRowIndex;\r
-                       if ( defaultValuesRowIndex != -1) {\r
+                       if (defaultValuesRowIndex != -1) {\r
                                // store default value in the table\r
-                               DataContainer[defaultValuesRowIndex] = _defaultValue;\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
+                               DataContainer.FillValues (defaultValuesRowIndex);\r
                        }\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
+               internal static bool AreColumnSetsTheSame (DataColumn [] columnSet, DataColumn [] compareSet)\r
                {\r
-                       if (null == columnSet && null == compareSet) {\r
+                       if (null == columnSet && null == compareSet)\r
                                return true;\r
-                       }\r
 \r
-                       if (null == columnSet || null == compareSet) {\r
+                       if (null == columnSet || null == compareSet)\r
                                return false;\r
-                       }\r
 \r
-                       if (columnSet.Length != compareSet.Length) { \r
+                       if (columnSet.Length != compareSet.Length)\r
                                return false;\r
-                       }\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
+                                       if (col == compare)\r
+                                               matchFound = true;\r
                                }\r
-                               if (! matchFound) {\r
+                               if (!matchFound)\r
                                        return false;\r
-                               }\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
+                       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
                internal void ResetColumnInfo ()\r
                {\r
                        _ordinal = -1;\r
@@ -992,7 +885,7 @@ namespace System.Data {
 \r
                        if (DateTimeMode == col.DateTimeMode)\r
                                return true;\r
-                       \r
+\r
                        if (DateTimeMode == DataSetDateTime.Local || DateTimeMode == DataSetDateTime.Utc)\r
                                return false;\r
 \r
@@ -1001,6 +894,51 @@ namespace System.Data {
 #endif\r
                        return true;\r
                }\r
+\r
+               internal static object GetDefaultValueForType (Type type)\r
+               {\r
+#if NET_2_0\r
+                       if (type == null)\r
+                               return DBNull.Value;\r
+                       if (type.Namespace == "System.Data.SqlTypes" && type.Assembly == typeof (DataColumn).Assembly) {\r
+                               // For SqlXxx types, set SqlXxx.Null instead of DBNull.Value.\r
+                               if (type == typeof (SqlBinary))\r
+                                       return SqlBinary.Null;\r
+                               if (type == typeof (SqlBoolean))\r
+                                       return SqlBoolean.Null;\r
+                               if (type == typeof (SqlByte))\r
+                                       return SqlByte.Null;\r
+                               if (type == typeof (SqlBytes))\r
+                                       return SqlBytes.Null;\r
+                               if (type == typeof (SqlChars))\r
+                                       return SqlChars.Null;\r
+                               if (type == typeof (SqlDateTime))\r
+                                       return SqlDateTime.Null;\r
+                               if (type == typeof (SqlDecimal))\r
+                                       return SqlDecimal.Null;\r
+                               if (type == typeof (SqlDouble))\r
+                                       return SqlDouble.Null;\r
+                               if (type == typeof (SqlGuid))\r
+                                       return SqlGuid.Null;\r
+                               if (type == typeof (SqlInt16))\r
+                                       return SqlInt16.Null;\r
+                               if (type == typeof (SqlInt32))\r
+                                       return SqlInt32.Null;\r
+                               if (type == typeof (SqlInt64))\r
+                                       return SqlInt64.Null;\r
+                               if (type == typeof (SqlMoney))\r
+                                       return SqlMoney.Null;\r
+                               if (type == typeof (SqlSingle))\r
+                                       return SqlSingle.Null;\r
+                               if (type == typeof (SqlString))\r
+                                       return SqlString.Null;\r
+                               if (type == typeof (SqlXml))\r
+                                       return SqlXml.Null;\r
+                       }\r
+#endif\r
+                       return DBNull.Value;\r
+               }\r
+\r
                #endregion // Methods\r
        }\r
 }\r