* DataColumn.cs (AllowDBNull) : Throw an exception.
authorEran Domb <eran@mono-cvs.ximian.com>
Sun, 9 Nov 2003 16:30:03 +0000 (16:30 -0000)
committerEran Domb <eran@mono-cvs.ximian.com>
Sun, 9 Nov 2003 16:30:03 +0000 (16:30 -0000)
* DataRow.cs (this[]) : First check if row is deleted.
(ItemArray) : First check if row is deleted.
(SetColumnValue) : Initiate error message when null violation happens. Check for array type when
setting the value of the row.
(EndEdit) : Check that the table's row is not in loading before validating constrains.
(CheckNullConstraints) : new method for validating null constraint violations.

* DataRowCollection.cs (ValidateDataRowInternal) : Adding validation of null constraint violation.

* DataSet.cs (CaseSensitive) : After changing the value - check constrains.
(EnforceConstraints) : When changing the value to true assert all constraints.

* UniqueConstraint.cs (AssertConstraint,CalcHashValue, RowsComparer) : Adding support for case insensitive comparison.

svn path=/trunk/mcs/; revision=19764

mcs/class/System.Data/System.Data/DataColumn.cs
mcs/class/System.Data/System.Data/DataRow.cs
mcs/class/System.Data/System.Data/DataRowCollection.cs
mcs/class/System.Data/System.Data/DataSet.cs
mcs/class/System.Data/System.Data/UniqueConstraint.cs

index 08206fd99db1141f0a854a262339225369b354fd..b9c7982fb04e0b499500391d503163ee0d9caa6b 100644 (file)
@@ -137,6 +137,8 @@ namespace System.Data {
                                                        }
                                                }
                                                
+                                               if (nullsFound)
+                                                       throw new DataException("Column '" + ColumnName + "' has null values in it.");
                                                //TODO: Validate no null values exist
                                                //do we also check different versions of the row??
                                        }
index 64be0023c72b4f2e7a29f60d210e0710ef201348..754ac6820697e51663f39aa8abeb3526eebb17c8 100644 (file)
-//\r
-// System.Data.DataRow.cs\r
-//\r
-// Author:\r
-//   Rodrigo Moya <rodrigo@ximian.com>\r
-//   Daniel Morgan <danmorg@sc.rr.com>\r
-//   Tim Coleman <tim@timcoleman.com>\r
-//   Ville Palo <vi64pa@koti.soon.fi>\r
-//   Alan Tam Siu Lung <Tam@SiuLung.com>\r
-//\r
-// (C) Ximian, Inc 2002\r
-// (C) Daniel Morgan 2002, 2003\r
-// Copyright (C) 2002 Tim Coleman\r
-//\r
-\r
-using System;\r
-using System.Collections;\r
-using System.Globalization;\r
-\r
-namespace System.Data {\r
-       /// <summary>\r
-       /// Represents a row of data in a DataTable.\r
-       /// </summary>\r
-       [Serializable]\r
-       public class DataRow\r
-       {\r
-               #region Fields\r
-\r
-               private DataTable _table;\r
-\r
-               private object[] original;\r
-               private object[] proposed;\r
-               private object[] current;\r
-\r
-               private string[] columnErrors;\r
-               private string rowError;\r
-               private DataRowState rowState;\r
-               internal int xmlRowID = 0;\r
-               internal bool _nullConstraintViolation;\r
-               private bool editing = false;\r
-               private bool _hasParentCollection;\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-\r
-               /// <summary>\r
-               /// This member supports the .NET Framework infrastructure and is not intended to be \r
-               /// used directly from your code.\r
-               /// </summary>\r
-               protected internal DataRow (DataRowBuilder builder)\r
-               {\r
-                       _table = builder.Table;\r
-\r
-                       original = null; \r
-                       \r
-                       proposed = new object[_table.Columns.Count];\r
-                       for (int c = 0; c < _table.Columns.Count; c++) \r
-                       {\r
-                               proposed[c] = DBNull.Value;\r
-                       }\r
-                       \r
-                       columnErrors = new string[_table.Columns.Count];\r
-                       rowError = String.Empty;\r
-\r
-                       //on first creating a DataRow it is always detached.\r
-                       rowState = DataRowState.Detached;\r
-                       \r
-                       foreach (DataColumn Col in _table.Columns) {\r
-                               \r
-                               if (Col.AutoIncrement) {\r
-                                       this [Col] = Col.AutoIncrementValue();\r
-                               }\r
-                       }\r
-                       _table.Columns.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(CollectionChanged);\r
-               }\r
-\r
-               \r
-               #endregion\r
-\r
-               #region Properties\r
-\r
-               /// <summary>\r
-               /// Gets a value indicating whether there are errors in a row.\r
-               /// </summary>\r
-               public bool HasErrors {\r
-                       [MonoTODO]\r
-                       get {\r
-                               if (RowError != string.Empty)\r
-                                       return true;\r
-\r
-                               for (int i= 0; i < columnErrors.Length; i++){\r
-                                       if (columnErrors[i] != null && columnErrors[i] != string.Empty)\r
-                                               return true;\r
-                               }\r
-\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets or sets the data stored in the column specified by name.\r
-               /// </summary>\r
-               public object this[string columnName] {\r
-                       get { return this[columnName, DataRowVersion.Default]; }\r
-                       set {\r
-                               int columnIndex = _table.Columns.IndexOf (columnName);\r
-                               if (columnIndex == -1)\r
-                                       throw new IndexOutOfRangeException ();\r
-                               this[columnIndex] = value;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets or sets the data stored in specified DataColumn\r
-               /// </summary>\r
-               public object this[DataColumn column] {\r
-\r
-                       get {\r
-                               return this[column, DataRowVersion.Default];} \r
-                       set {\r
-                               int columnIndex = _table.Columns.IndexOf (column);\r
-                               if (columnIndex == -1)\r
-                                       throw new ArgumentException ("The column does not belong to this table.");\r
-                               this[columnIndex] = value;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets or sets the data stored in column specified by index.\r
-               /// </summary>\r
-               public object this[int columnIndex] {\r
-                       get { return this[columnIndex, DataRowVersion.Default]; }\r
-                       set {\r
-                               if (columnIndex < 0 || columnIndex > _table.Columns.Count)\r
-                                       throw new IndexOutOfRangeException ();\r
-                               if (rowState == DataRowState.Deleted)\r
-                                       throw new DeletedRowInaccessibleException ();\r
-                               DataColumn column = _table.Columns[columnIndex];\r
-                               _table.ChangingDataColumn (this, column, value);\r
-                               \r
-                               \r
-                               bool orginalEditing = editing;\r
-                               if (!orginalEditing) BeginEdit ();\r
-                               object v = SetColumnValue (value, columnIndex);\r
-                               proposed[columnIndex] = v;\r
-                               _table.ChangedDataColumn (this, column, v);\r
-                               if (!orginalEditing) EndEdit ();\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the specified version of data stored in the named column.\r
-               /// </summary>\r
-               public object this[string columnName, DataRowVersion version] {\r
-                       get {\r
-                               int columnIndex = _table.Columns.IndexOf (columnName);\r
-                               if (columnIndex == -1)\r
-                                       throw new IndexOutOfRangeException ();\r
-                               return this[columnIndex, version];\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the specified version of data stored in the specified DataColumn.\r
-               /// </summary>\r
-               public object this[DataColumn column, DataRowVersion version] {\r
-                       get {\r
-                               int columnIndex = _table.Columns.IndexOf (column);\r
-                               if (columnIndex == -1)\r
-                                       throw new ArgumentException ("The column does not belong to this table.");\r
-                               return this[columnIndex, version];\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the data stored in the column, specified by index and version of the data to\r
-               /// retrieve.\r
-               /// </summary>\r
-               public object this[int columnIndex, DataRowVersion version] {\r
-                       get {\r
-                               if (columnIndex < 0 || columnIndex > _table.Columns.Count)\r
-                                       throw new IndexOutOfRangeException ();\r
-                               // Non-existent version\r
-                               if (rowState == DataRowState.Detached && version == DataRowVersion.Current || !HasVersion (version))\r
-                                       throw new VersionNotFoundException (Locale.GetText ("There is no " + version.ToString () + " data to access."));\r
+//
+// System.Data.DataRow.cs
+//
+// Author:
+//   Rodrigo Moya <rodrigo@ximian.com>
+//   Daniel Morgan <danmorg@sc.rr.com>
+//   Tim Coleman <tim@timcoleman.com>
+//   Ville Palo <vi64pa@koti.soon.fi>
+//   Alan Tam Siu Lung <Tam@SiuLung.com>
+//
+// (C) Ximian, Inc 2002
+// (C) Daniel Morgan 2002, 2003
+// Copyright (C) 2002 Tim Coleman
+//
+
+using System;
+using System.Collections;
+using System.Globalization;
+
+namespace System.Data {
+       /// <summary>
+       /// Represents a row of data in a DataTable.
+       /// </summary>
+       [Serializable]
+       public class DataRow
+       {
+               #region Fields
+
+               private DataTable _table;
+
+               private object[] original;
+               private object[] proposed;
+               private object[] current;
+
+               private string[] columnErrors;
+               private string rowError;
+               private DataRowState rowState;
+               internal int xmlRowID = 0;
+               internal bool _nullConstraintViolation;
+               private string _nullConstraintMessage;
+               private bool editing = false;
+               private bool _hasParentCollection;
+
+               #endregion
+
+               #region Constructors
+
+               /// <summary>
+               /// This member supports the .NET Framework infrastructure and is not intended to be 
+               /// used directly from your code.
+               /// </summary>
+               protected internal DataRow (DataRowBuilder builder)
+               {
+                       _table = builder.Table;
+
+                       original = null; 
+                       
+                       proposed = new object[_table.Columns.Count];
+                       for (int c = 0; c < _table.Columns.Count; c++) 
+                       {
+                               proposed[c] = DBNull.Value;
+                       }
+                       
+                       columnErrors = new string[_table.Columns.Count];
+                       rowError = String.Empty;
+
+                       //on first creating a DataRow it is always detached.
+                       rowState = DataRowState.Detached;
+                       
+                       foreach (DataColumn Col in _table.Columns) {
+                               
+                               if (Col.AutoIncrement) {
+                                       this [Col] = Col.AutoIncrementValue();
+                               }
+                       }
+                       _table.Columns.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(CollectionChanged);
+               }
+
+               
+               #endregion
+
+               #region Properties
+
+               /// <summary>
+               /// Gets a value indicating whether there are errors in a row.
+               /// </summary>
+               public bool HasErrors {
+                       [MonoTODO]
+                       get {
+                               if (RowError != string.Empty)
+                                       return true;
+
+                               for (int i= 0; i < columnErrors.Length; i++){
+                                       if (columnErrors[i] != null && columnErrors[i] != string.Empty)
+                                               return true;
+                               }
+
+                               return false;
+                       }
+               }
+
+               /// <summary>
+               /// Gets or sets the data stored in the column specified by name.
+               /// </summary>
+               public object this[string columnName] {
+                       get { return this[columnName, DataRowVersion.Default]; }
+                       set {
+                               int columnIndex = _table.Columns.IndexOf (columnName);
+                               if (columnIndex == -1)
+                                       throw new IndexOutOfRangeException ();
+                               this[columnIndex] = value;
+                       }
+               }
+
+               /// <summary>
+               /// Gets or sets the data stored in specified DataColumn
+               /// </summary>
+               public object this[DataColumn column] {
+
+                       get {
+                               return this[column, DataRowVersion.Default];} 
+                       set {
+                               int columnIndex = _table.Columns.IndexOf (column);
+                               if (columnIndex == -1)
+                                       throw new ArgumentException ("The column does not belong to this table.");
+                               this[columnIndex] = value;
+                       }
+               }
+
+               /// <summary>
+               /// Gets or sets the data stored in column specified by index.
+               /// </summary>
+               public object this[int columnIndex] {
+                       get { return this[columnIndex, DataRowVersion.Default]; }
+                       set {
+                               if (columnIndex < 0 || columnIndex > _table.Columns.Count)
+                                       throw new IndexOutOfRangeException ();
+                               if (rowState == DataRowState.Deleted)
+                                       throw new DeletedRowInaccessibleException ();
+                               DataColumn column = _table.Columns[columnIndex];
+                               _table.ChangingDataColumn (this, column, value);
+                               
+                               
+                               bool orginalEditing = editing;
+                               if (!orginalEditing) BeginEdit ();
+                               object v = SetColumnValue (value, columnIndex);
+                               proposed[columnIndex] = v;
+                               _table.ChangedDataColumn (this, column, v);
+                               if (!orginalEditing) EndEdit ();
+                       }
+               }
+
+               /// <summary>
+               /// Gets the specified version of data stored in the named column.
+               /// </summary>
+               public object this[string columnName, DataRowVersion version] {
+                       get {
+                               int columnIndex = _table.Columns.IndexOf (columnName);
+                               if (columnIndex == -1)
+                                       throw new IndexOutOfRangeException ();
+                               return this[columnIndex, version];
+                       }
+               }
+
+               /// <summary>
+               /// Gets the specified version of data stored in the specified DataColumn.
+               /// </summary>
+               public object this[DataColumn column, DataRowVersion version] {
+                       get {
+                               int columnIndex = _table.Columns.IndexOf (column);
+                               if (columnIndex == -1)
+                                       throw new ArgumentException ("The column does not belong to this table.");
+                               return this[columnIndex, version];
+                       }
+               }
+
+               /// <summary>
+               /// Gets the data stored in the column, specified by index and version of the data to
+               /// retrieve.
+               /// </summary>
+               public object this[int columnIndex, DataRowVersion version] {
+                       get {
+                               if (columnIndex < 0 || columnIndex > _table.Columns.Count)
+                                       throw new IndexOutOfRangeException ();
+                               // Accessing deleted rows
+                               if (rowState == DataRowState.Deleted && version != DataRowVersion.Original)
+                                       throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");
+                               // Non-existent version
+                               if (rowState == DataRowState.Detached && version == DataRowVersion.Current || !HasVersion (version))
+                                       throw new VersionNotFoundException (Locale.GetText ("There is no " + version.ToString () + " data to access."));
+                               switch (version) {
+                               case DataRowVersion.Default:
+                                       if (editing || rowState == DataRowState.Detached)
+                                               return proposed[columnIndex];
+                                       return current[columnIndex];
+                               case DataRowVersion.Proposed:
+                                       return proposed[columnIndex];
+                               case DataRowVersion.Current:
+                                       return current[columnIndex];
+                               case DataRowVersion.Original:
+                                       return original[columnIndex];
+                               default:
+                                       throw new ArgumentException ();
+                               }
+                       }
+               }
+
+               /// <summary>
+               /// Gets or sets all of the values for this row through an array.
+               /// </summary>
+               [MonoTODO]
+               public object[] ItemArray {
+                       get { 
                                // Accessing deleted rows\r
-                               if (rowState == DataRowState.Deleted && version != DataRowVersion.Original)\r
-                                       throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");\r
-                               switch (version) {\r
-                               case DataRowVersion.Default:\r
-                                       if (editing || rowState == DataRowState.Detached)\r
-                                               return proposed[columnIndex];\r
-                                       return current[columnIndex];\r
-                               case DataRowVersion.Proposed:\r
-                                       return proposed[columnIndex];\r
-                               case DataRowVersion.Current:\r
-                                       return current[columnIndex];\r
-                               case DataRowVersion.Original:\r
-                                       return original[columnIndex];\r
-                               default:\r
-                                       throw new ArgumentException ();\r
-                               }\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets or sets all of the values for this row through an array.\r
-               /// </summary>\r
-               [MonoTODO]\r
-               public object[] ItemArray {\r
-                       get { \r
-                               return current; \r
-                       }\r
-                       set {\r
-                               if (value.Length > _table.Columns.Count)\r
-                                       throw new ArgumentException ();\r
-\r
                                if (rowState == DataRowState.Deleted)\r
-                                       throw new DeletedRowInaccessibleException ();\r
-                               \r
-                               object[] newItems = new object[_table.Columns.Count];                   \r
-                               object v = null;\r
-                               for (int i = 0; i < _table.Columns.Count; i++) {\r
-\r
-                                       if (i < value.Length)\r
-                                               v = value[i];\r
-                                       else\r
-                                               v = null;\r
-\r
-                                       newItems[i] = SetColumnValue (v, i);\r
-                               }\r
-\r
-                               bool orginalEditing = editing;\r
-                               if (!orginalEditing) BeginEdit ();\r
-                               proposed = newItems;\r
-                               if (!orginalEditing) EndEdit ();\r
-                       }\r
-               }\r
-\r
+                                       throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");\r
+                               
+                               return current; 
+                       }
+                       set {
+                               if (value.Length > _table.Columns.Count)
+                                       throw new ArgumentException ();
+
+                               if (rowState == DataRowState.Deleted)
+                                       throw new DeletedRowInaccessibleException ();
+                               
+                               object[] newItems = new object[_table.Columns.Count];                   
+                               object v = null;
+                               for (int i = 0; i < _table.Columns.Count; i++) {
+
+                                       if (i < value.Length)
+                                               v = value[i];
+                                       else
+                                               v = null;
+
+                                       newItems[i] = SetColumnValue (v, i);
+                               }
+
+                               bool orginalEditing = editing;
+                               if (!orginalEditing) BeginEdit ();
+                               proposed = newItems;
+                               if (!orginalEditing) EndEdit ();
+                       }
+               }
+
                private object SetColumnValue (object v, int index) \r
                {               \r
                        object newval = null;\r
@@ -260,21 +265,12 @@ namespace System.Data {
                                {\r
                                        if (!col.AllowDBNull)\r
                                        {\r
-                                               if (!this._table._duringDataLoad)\r
-                                               {\r
-                                                       throw new NoNullAllowedException ();\r
-                                               }\r
-                                               else \r
-                                               {\r
-                                                       //Constraint violations during data load is raise in DataTable EndLoad\r
-                                                       this._nullConstraintViolation = true;\r
-                                                       \r
-                                               }\r
+                                               //Constraint violations during data load is raise in DataTable EndLoad\r
+                                               this._nullConstraintViolation = true;\r
+                                               _nullConstraintMessage = "Column '" + col.ColumnName + "' does not allow nulls.";\r
                                        }\r
 \r
-                                       newval= DBNull.Value;\r
-                                       \r
-                               \r
+                                       newval = DBNull.Value;\r
                                }\r
                        }               \r
                        else if (v == DBNull.Value) \r
@@ -282,18 +278,12 @@ namespace System.Data {
                                \r
                                if (!col.AllowDBNull)\r
                                {\r
-                                       if (!this._table._duringDataLoad)\r
-                                       {\r
-                                               throw new NoNullAllowedException ();\r
-                                       }\r
-                                       else \r
-                                       {\r
-                                               //Constraint violations during data load is raise in DataTable EndLoad\r
-                                               this._nullConstraintViolation = true;\r
-                                                       \r
-                                       }\r
+                                       //Constraint violations during data load is raise in DataTable EndLoad\r
+                                       this._nullConstraintViolation = true;\r
+                                       _nullConstraintMessage = "Column '" + col.ColumnName + "' does not allow nulls.";\r
                                }\r
-                               newval= DBNull.Value;\r
+                               \r
+                               newval = DBNull.Value;\r
                        }\r
                        else \r
                        {       \r
@@ -303,69 +293,71 @@ namespace System.Data {
                                {\r
                                        TypeCode typeCode = Type.GetTypeCode(cType);\r
                                        switch(typeCode) {\r
-                                       case TypeCode.Boolean :\r
-                                               v = Convert.ToBoolean (v);\r
-                                               break;\r
-                                       case TypeCode.Byte  :\r
-                                               v = Convert.ToByte (v);\r
-                                               break;\r
-                                       case TypeCode.Char  :\r
-                                               v = Convert.ToChar (v);\r
-                                               break;\r
-                                       case TypeCode.DateTime  :\r
-                                               v = Convert.ToDateTime (v);\r
-                                               break;\r
-                                       case TypeCode.Decimal  :\r
-                                               v = Convert.ToDecimal (v);\r
-                                               break;\r
-                                       case TypeCode.Double  :\r
-                                               v = Convert.ToDouble (v);\r
-                                               break;\r
-                                       case TypeCode.Int16  :\r
-                                               v = Convert.ToInt16 (v);\r
-                                               break;\r
-                                       case TypeCode.Int32  :\r
-                                               v = Convert.ToInt32 (v);\r
-                                               break;\r
-                                       case TypeCode.Int64  :\r
-                                               v = Convert.ToInt64 (v);\r
-                                               break;\r
-                                       case TypeCode.SByte  :\r
-                                               v = Convert.ToSByte (v);\r
-                                               break;\r
-                                       case TypeCode.Single  :\r
-                                               v = Convert.ToSingle (v);\r
-                                               break;\r
-                                       case TypeCode.String  :\r
-                                               v = Convert.ToString (v);\r
-                                               break;\r
-                                       case TypeCode.UInt16  :\r
-                                               v = Convert.ToUInt16 (v);\r
-                                               break;\r
-                                       case TypeCode.UInt32  :\r
-                                               v = Convert.ToUInt32 (v);\r
-                                               break;\r
-                                       case TypeCode.UInt64  :\r
-                                               v = Convert.ToUInt64 (v);\r
-                                               break;\r
-                                       default :\r
-                                       switch(cType.ToString()) {\r
-                                               case "System.TimeSpan" :\r
-                                                       v = (System.TimeSpan) v;\r
+                                               case TypeCode.Boolean :\r
+                                                       v = Convert.ToBoolean (v);\r
+                                                       break;\r
+                                               case TypeCode.Byte  :\r
+                                                       v = Convert.ToByte (v);\r
+                                                       break;\r
+                                               case TypeCode.Char  :\r
+                                                       v = Convert.ToChar (v);\r
+                                                       break;\r
+                                               case TypeCode.DateTime  :\r
+                                                       v = Convert.ToDateTime (v);\r
+                                                       break;\r
+                                               case TypeCode.Decimal  :\r
+                                                       v = Convert.ToDecimal (v);\r
+                                                       break;\r
+                                               case TypeCode.Double  :\r
+                                                       v = Convert.ToDouble (v);\r
+                                                       break;\r
+                                               case TypeCode.Int16  :\r
+                                                       v = Convert.ToInt16 (v);\r
+                                                       break;\r
+                                               case TypeCode.Int32  :\r
+                                                       v = Convert.ToInt32 (v);\r
                                                        break;\r
-                                               case "System.Type" :\r
-                                                       v = (System.Type) v;\r
+                                               case TypeCode.Int64  :\r
+                                                       v = Convert.ToInt64 (v);\r
                                                        break;\r
-                                               case "System.Object" :\r
-                                                       //v = (System.Object) v;\r
+                                               case TypeCode.SByte  :\r
+                                                       v = Convert.ToSByte (v);\r
+                                                       break;\r
+                                               case TypeCode.Single  :\r
+                                                       v = Convert.ToSingle (v);\r
+                                                       break;\r
+                                               case TypeCode.String  :\r
+                                                       v = Convert.ToString (v);\r
+                                                       break;\r
+                                               case TypeCode.UInt16  :\r
+                                                       v = Convert.ToUInt16 (v);\r
+                                                       break;\r
+                                               case TypeCode.UInt32  :\r
+                                                       v = Convert.ToUInt32 (v);\r
+                                                       break;\r
+                                               case TypeCode.UInt64  :\r
+                                                       v = Convert.ToUInt64 (v);\r
+                                                       break;\r
+                                               default :\r
+                                                               \r
+                                               switch(cType.ToString()) {\r
+                                                       case "System.TimeSpan" :\r
+                                                               v = (System.TimeSpan) v;\r
+                                                               break;\r
+                                                       case "System.Type" :\r
+                                                               v = (System.Type) v;\r
+                                                               break;\r
+                                                       case "System.Object" :\r
+                                                               //v = (System.Object) v;\r
+                                                               break;\r
+                                                       default:\r
+                                                               if (!cType.IsArray)\r
+                                                                       throw new InvalidCastException("Type not supported.");\r
+                                                               break;\r
+                                               }\r
                                                        break;\r
-                                               default:\r
-                                                       // FIXME: is exception correct?\r
-                                                       throw new InvalidCastException("Type not supported.");\r
                                        }\r
-                                               break;\r
-                               }\r
-                               vType = v.GetType();\r
+                                       vType = v.GetType();\r
                                }\r
                                newval = v;\r
                                if(col.AutoIncrement == true) {\r
@@ -376,273 +368,277 @@ namespace System.Data {
                        col.DataHasBeenSet = true;\r
                        return newval;\r
                }\r
-\r
-               /// <summary>\r
-               /// Gets or sets the custom error description for a row.\r
-               /// </summary>\r
-               public string RowError {\r
-                       get { return rowError; }\r
-                       set { rowError = value; }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the current state of the row in regards to its relationship to the\r
-               /// DataRowCollection.\r
-               /// </summary>\r
-               public DataRowState RowState {\r
-                       get { return rowState; }\r
-               }\r
-\r
-               //FIXME?: Couldn't find a way to set the RowState when adding the DataRow\r
-               //to a Datatable so I added this method. Delete if there is a better way.\r
-               internal void AttachRow() {\r
-                       current = proposed;\r
-                       proposed = null;\r
-                       rowState = DataRowState.Added;\r
-               }\r
-\r
-               //FIXME?: Couldn't find a way to set the RowState when removing the DataRow\r
-               //from a Datatable so I added this method. Delete if there is a better way.\r
-               internal void DetachRow() {\r
-                       proposed = null;\r
-                       _hasParentCollection = false;\r
-                       rowState = DataRowState.Detached;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the DataTable for which this row has a schema.\r
-               /// </summary>\r
-               public DataTable Table {\r
-                       get { return _table; }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets and sets index of row. This is used from \r
-               /// XmlDataDocument.\r
-               // </summary>\r
-               internal int XmlRowID {\r
-                       get { return xmlRowID; }\r
-                       set { xmlRowID = value; }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Methods\r
-\r
-               /// <summary>\r
-               /// Commits all the changes made to this row since the last time AcceptChanges was\r
-               /// called.\r
-               /// </summary>\r
-               public void AcceptChanges () \r
-               {\r
-                       EndEdit(); // in case it hasn't been called\r
-                       switch (rowState) {\r
-                       case DataRowState.Added:\r
-                       case DataRowState.Modified:\r
-                               rowState = DataRowState.Unchanged;\r
-                               break;\r
-                       case DataRowState.Deleted:\r
-                               _table.Rows.Remove (this);\r
-                               break;\r
-                       case DataRowState.Detached:\r
-                               throw new RowNotInTableException("Cannot perform this operation on a row not in the table.");\r
-                       }\r
-                       // Accept from detached\r
-                       if (original == null)\r
-                               original = new object[_table.Columns.Count];\r
-                       Array.Copy (current, original, _table.Columns.Count);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Begins an edit operation on a DataRow object.\r
-               /// </summary>\r
-               [MonoTODO]\r
-               public void BeginEdit () \r
-               {\r
-                       if (rowState == DataRowState.Deleted)\r
-                               throw new DeletedRowInaccessibleException ();\r
-                       if (!HasVersion (DataRowVersion.Proposed)) {\r
-                               proposed = new object[_table.Columns.Count];\r
-                               Array.Copy (current, proposed, current.Length);\r
-                       }\r
-                       //TODO: Suspend validation\r
-                       editing = true;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Cancels the current edit on the row.\r
-               /// </summary>\r
-               [MonoTODO]\r
-               public void CancelEdit () \r
-               {\r
-                       editing = false;\r
-                       //TODO: Events\r
-                       if (HasVersion (DataRowVersion.Proposed)) {\r
-                               proposed = null;\r
-                               if (rowState == DataRowState.Modified)\r
-                                   rowState = DataRowState.Unchanged;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Clears the errors for the row, including the RowError and errors set with\r
-               /// SetColumnError.\r
-               /// </summary>\r
-               public void ClearErrors () \r
-               {\r
-                       rowError = String.Empty;\r
-                       columnErrors = new String[_table.Columns.Count];\r
-               }\r
-\r
-               /// <summary>\r
-               /// Deletes the DataRow.\r
-               /// </summary>\r
-               [MonoTODO]\r
-               public void Delete () \r
-               {\r
-                       switch (rowState) {\r
-                       case DataRowState.Added:\r
-                               Table.Rows.Remove (this);\r
-                               break;\r
-                       case DataRowState.Deleted:\r
-                               throw new DeletedRowInaccessibleException ();\r
-                       default:\r
-                               _table.DeletingDataRow(this, DataRowAction.Delete);\r
-                               // check what to do with child rows\r
-                               CheckChildRows(DataRowAction.Delete);\r
-                               rowState = DataRowState.Deleted;\r
-                               _table.DeletedDataRow(this, DataRowAction.Delete);\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               // check the child rows of this row before deleting the row.\r
-               private void CheckChildRows(DataRowAction action)\r
-               {\r
-                       \r
-                       // in this method we find the row that this row is in a reltion with them.\r
-                       // in shortly we find all child rows of this row.\r
-                       // then we function according to the DeleteRule of the foriegnkey.\r
-\r
-\r
-                       // 1. find if this row is attached to dataset.\r
-                       // 2. find if EnforceConstraints is true.\r
-                       // 3. find if there are any constraint on the table that the row is in.\r
-                       if (_table.DataSet != null && _table.DataSet.EnforceConstraints && _table.Constraints.Count > 0)\r
-                       {\r
-                               foreach (DataTable table in _table.DataSet.Tables)\r
-                               {\r
-                                       // loop on all constraints of the table.\r
-                                       ConstraintCollection constraintsCollection = table.Constraints;\r
-                                       for (int i = 0; i < constraintsCollection.Count; i++)\r
-                                       {\r
-                                               ForeignKeyConstraint fk = null;\r
-                                               if (constraintsCollection[i] is ForeignKeyConstraint)\r
-                                               {\r
-                                                       fk = (ForeignKeyConstraint)constraintsCollection[i];\r
-                                                       if (fk.RelatedTable == _table)\r
-                                                       {\r
-                                                               //we create a dummy relation because we do not want to duplicate code of GetChild().\r
-                                                               // we use the dummy relation to find child rows.\r
-                                                               DataRelation rel = new DataRelation("dummy", fk.RelatedColumns, fk.Columns, false);\r
-                                                               Rule rule;\r
-                                                               if (action == DataRowAction.Delete)\r
-                                                                       rule = fk.DeleteRule;\r
-                                                               else\r
-                                                                       rule = fk.UpdateRule;\r
-                                                               CheckChildRows(rel, action, rule);\r
-                                                       }\r
-                                               }                       \r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-\r
-               private void CheckChildRows(DataRelation rel, DataRowAction action, Rule rule)\r
-               {                               \r
-                       DataRow[] childRows = GetChildRows(rel);\r
-                       switch (rule)\r
+
+
+               /// <summary>
+               /// Gets or sets the custom error description for a row.
+               /// </summary>
+               public string RowError {
+                       get { return rowError; }
+                       set { rowError = value; }
+               }
+
+               /// <summary>
+               /// Gets the current state of the row in regards to its relationship to the
+               /// DataRowCollection.
+               /// </summary>
+               public DataRowState RowState {
+                       get { return rowState; }
+               }
+
+               //FIXME?: Couldn't find a way to set the RowState when adding the DataRow
+               //to a Datatable so I added this method. Delete if there is a better way.
+               internal void AttachRow() {
+                       current = proposed;
+                       proposed = null;
+                       rowState = DataRowState.Added;
+               }
+
+               //FIXME?: Couldn't find a way to set the RowState when removing the DataRow
+               //from a Datatable so I added this method. Delete if there is a better way.
+               internal void DetachRow() {
+                       proposed = null;
+                       _hasParentCollection = false;
+                       rowState = DataRowState.Detached;
+               }
+
+               /// <summary>
+               /// Gets the DataTable for which this row has a schema.
+               /// </summary>
+               public DataTable Table {
+                       get { return _table; }
+               }
+
+               /// <summary>
+               /// Gets and sets index of row. This is used from 
+               /// XmlDataDocument.
+               // </summary>
+               internal int XmlRowID {
+                       get { return xmlRowID; }
+                       set { xmlRowID = value; }
+               }
+
+               #endregion
+
+               #region Methods
+
+               /// <summary>
+               /// Commits all the changes made to this row since the last time AcceptChanges was
+               /// called.
+               /// </summary>
+               public void AcceptChanges () 
+               {
+                       EndEdit(); // in case it hasn't been called
+                       switch (rowState) {
+                       case DataRowState.Added:
+                       case DataRowState.Modified:
+                               rowState = DataRowState.Unchanged;
+                               break;
+                       case DataRowState.Deleted:
+                               _table.Rows.Remove (this);
+                               break;
+                       case DataRowState.Detached:
+                               throw new RowNotInTableException("Cannot perform this operation on a row not in the table.");
+                       }
+                       // Accept from detached
+                       if (original == null)
+                               original = new object[_table.Columns.Count];
+                       Array.Copy (current, original, _table.Columns.Count);
+               }
+
+               /// <summary>
+               /// Begins an edit operation on a DataRow object.
+               /// </summary>
+               [MonoTODO]
+               public void BeginEdit () 
+               {
+                       if (rowState == DataRowState.Deleted)
+                               throw new DeletedRowInaccessibleException ();
+                       if (!HasVersion (DataRowVersion.Proposed)) {
+                               proposed = new object[_table.Columns.Count];
+                               Array.Copy (current, proposed, current.Length);
+                       }
+                       //TODO: Suspend validation
+                       editing = true;
+               }
+
+               /// <summary>
+               /// Cancels the current edit on the row.
+               /// </summary>
+               [MonoTODO]
+               public void CancelEdit () 
+               {
+                       editing = false;
+                       //TODO: Events
+                       if (HasVersion (DataRowVersion.Proposed)) {
+                               proposed = null;
+                               if (rowState == DataRowState.Modified)
+                                   rowState = DataRowState.Unchanged;
+                       }
+               }
+
+               /// <summary>
+               /// Clears the errors for the row, including the RowError and errors set with
+               /// SetColumnError.
+               /// </summary>
+               public void ClearErrors () 
+               {
+                       rowError = String.Empty;
+                       columnErrors = new String[_table.Columns.Count];
+               }
+
+               /// <summary>
+               /// Deletes the DataRow.
+               /// </summary>
+               [MonoTODO]
+               public void Delete () 
+               {
+                       switch (rowState) {
+                       case DataRowState.Added:
+                               Table.Rows.Remove (this);
+                               break;
+                       case DataRowState.Deleted:
+                               throw new DeletedRowInaccessibleException ();
+                       default:
+                               _table.DeletingDataRow(this, DataRowAction.Delete);
+                               // check what to do with child rows
+                               CheckChildRows(DataRowAction.Delete);
+                               rowState = DataRowState.Deleted;
+                               _table.DeletedDataRow(this, DataRowAction.Delete);
+                               break;
+                       }
+               }
+
+               // check the child rows of this row before deleting the row.
+               private void CheckChildRows(DataRowAction action)
+               {
+                       
+                       // in this method we find the row that this row is in a reltion with them.
+                       // in shortly we find all child rows of this row.
+                       // then we function according to the DeleteRule of the foriegnkey.
+
+
+                       // 1. find if this row is attached to dataset.
+                       // 2. find if EnforceConstraints is true.
+                       // 3. find if there are any constraint on the table that the row is in.
+                       if (_table.DataSet != null && _table.DataSet.EnforceConstraints && _table.Constraints.Count > 0)
+                       {
+                               foreach (DataTable table in _table.DataSet.Tables)
+                               {
+                                       // loop on all constraints of the table.
+                                       ConstraintCollection constraintsCollection = table.Constraints;
+                                       for (int i = 0; i < constraintsCollection.Count; i++)
+                                       {
+                                               ForeignKeyConstraint fk = null;
+                                               if (constraintsCollection[i] is ForeignKeyConstraint)
+                                               {
+                                                       fk = (ForeignKeyConstraint)constraintsCollection[i];
+                                                       if (fk.RelatedTable == _table)
+                                                       {
+                                                               //we create a dummy relation because we do not want to duplicate code of GetChild().
+                                                               // we use the dummy relation to find child rows.
+                                                               DataRelation rel = new DataRelation("dummy", fk.RelatedColumns, fk.Columns, false);
+                                                               Rule rule;
+                                                               if (action == DataRowAction.Delete)
+                                                                       rule = fk.DeleteRule;
+                                                               else
+                                                                       rule = fk.UpdateRule;
+                                                               CheckChildRows(rel, action, rule);
+                                                       }
+                                               }                       
+                                       }
+                               }
+                       }
+               }
+
+               private void CheckChildRows(DataRelation rel, DataRowAction action, Rule rule)
+               {                               
+                       DataRow[] childRows = GetChildRows(rel);
+                       switch (rule)
+                       {
+                               case Rule.Cascade:  // delete or change all relted rows.
+                                       if (childRows != null)
+                                       {
+                                               for (int j = 0; j < childRows.Length; j++)
+                                               {
+                                                       // if action is delete we delete all child rows
+                                                       if (action == DataRowAction.Delete)
+                                                       {
+                                                               if (childRows[j].RowState != DataRowState.Deleted)
+                                                                       childRows[j].Delete();
+                                                       }
+                                                       // if action is change we change the values in the child row
+                                                       else if (action == DataRowAction.Change)
+                                                       {
+                                                               // change only the values in the key columns
+                                                               // set the childcolumn value to the new parent row value
+                                                               for (int k = 0; k < rel.ChildColumns.Length; k++)
+                                                                       childRows[j][rel.ChildColumns[k]] = this[rel.ParentColumns[k], DataRowVersion.Proposed];
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               case Rule.None: // throw an exception if there are any child rows.
+                                       if (childRows != null)
+                                       {
+                                               for (int j = 0; j < childRows.Length; j++)
+                                               {
+                                                       if (childRows[j].RowState != DataRowState.Deleted)
+                                                       {
+                                                               string changeStr = "Cannot change this row because constraints are enforced on relation " + rel.RelationName +", and changing this row will strand child rows.";
+                                                               string delStr = "Cannot delete this row because constraints are enforced on relation " + rel.RelationName +", and deleting this row will strand child rows.";
+                                                               string message = action == DataRowAction.Delete ? delStr : changeStr;
+                                                               throw new InvalidConstraintException(message);
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               case Rule.SetDefault: // set the values in the child rows to the defult value of the columns.
+                                       if (childRows != null)
+                                       {
+                                               for (int j = 0; j < childRows.Length; j++)
+                                               {
+                                                       DataRow child = childRows[j];
+                                                       if (childRows[j].RowState != DataRowState.Deleted)
+                                                       {
+                                                               //set only the key columns to default
+                                                               for (int k = 0; k < rel.ChildColumns.Length; k++)
+                                                                       child[rel.ChildColumns[k]] = rel.ChildColumns[k].DefaultValue;
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               case Rule.SetNull: // set the values in the child row to null.
+                                       if (childRows != null)
+                                       {
+                                               for (int j = 0; j < childRows.Length; j++)
+                                               {
+                                                       DataRow child = childRows[j];
+                                                       if (childRows[j].RowState != DataRowState.Deleted)
+                                                       {
+                                                               // set only the key columns to DBNull
+                                                               for (int k = 0; k < rel.ChildColumns.Length; k++)
+                                                                       child.SetNull(rel.ChildColumns[k]);
+                                                       }
+                                               }
+                                       }
+                                       break;
+                       }
+
+               }
+
+               /// <summary>
+               /// Ends the edit occurring on the row.
+               /// </summary>
+               [MonoTODO]
+               public void EndEdit () 
+               {
+                       if (rowState == DataRowState.Detached)\r
                        {\r
-                               case Rule.Cascade:  // delete or change all relted rows.\r
-                                       if (childRows != null)\r
-                                       {\r
-                                               for (int j = 0; j < childRows.Length; j++)\r
-                                               {\r
-                                                       // if action is delete we delete all child rows\r
-                                                       if (action == DataRowAction.Delete)\r
-                                                       {\r
-                                                               if (childRows[j].RowState != DataRowState.Deleted)\r
-                                                                       childRows[j].Delete();\r
-                                                       }\r
-                                                       // if action is change we change the values in the child row\r
-                                                       else if (action == DataRowAction.Change)\r
-                                                       {\r
-                                                               // change only the values in the key columns\r
-                                                               // set the childcolumn value to the new parent row value\r
-                                                               for (int k = 0; k < rel.ChildColumns.Length; k++)\r
-                                                                       childRows[j][rel.ChildColumns[k]] = this[rel.ParentColumns[k], DataRowVersion.Proposed];\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       break;\r
-                               case Rule.None: // throw an exception if there are any child rows.\r
-                                       if (childRows != null)\r
-                                       {\r
-                                               for (int j = 0; j < childRows.Length; j++)\r
-                                               {\r
-                                                       if (childRows[j].RowState != DataRowState.Deleted)\r
-                                                       {\r
-                                                               string changeStr = "Cannot change this row because constraints are enforced on relation " + rel.RelationName +", and changing this row will strand child rows.";\r
-                                                               string delStr = "Cannot delete this row because constraints are enforced on relation " + rel.RelationName +", and deleting this row will strand child rows.";\r
-                                                               string message = action == DataRowAction.Delete ? delStr : changeStr;\r
-                                                               throw new InvalidConstraintException(message);\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       break;\r
-                               case Rule.SetDefault: // set the values in the child rows to the defult value of the columns.\r
-                                       if (childRows != null)\r
-                                       {\r
-                                               for (int j = 0; j < childRows.Length; j++)\r
-                                               {\r
-                                                       DataRow child = childRows[j];\r
-                                                       if (childRows[j].RowState != DataRowState.Deleted)\r
-                                                       {\r
-                                                               //set only the key columns to default\r
-                                                               for (int k = 0; k < rel.ChildColumns.Length; k++)\r
-                                                                       child[rel.ChildColumns[k]] = rel.ChildColumns[k].DefaultValue;\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       break;\r
-                               case Rule.SetNull: // set the values in the child row to null.\r
-                                       if (childRows != null)\r
-                                       {\r
-                                               for (int j = 0; j < childRows.Length; j++)\r
-                                               {\r
-                                                       DataRow child = childRows[j];\r
-                                                       if (childRows[j].RowState != DataRowState.Deleted)\r
-                                                       {\r
-                                                               // set only the key columns to DBNull\r
-                                                               for (int k = 0; k < rel.ChildColumns.Length; k++)\r
-                                                                       child.SetNull(rel.ChildColumns[k]);\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       break;\r
+                               editing = false;\r
+                               return;\r
                        }\r
 \r
-               }\r
-\r
-               /// <summary>\r
-               /// Ends the edit occurring on the row.\r
-               /// </summary>\r
-               [MonoTODO]\r
-               public void EndEdit () \r
-               {\r
-                       editing = false;\r
-                       if (rowState == DataRowState.Detached)\r
-                               return;\r
                        if (HasVersion (DataRowVersion.Proposed))\r
                        {\r
                                _table.ChangingDataRow(this, DataRowAction.Change);\r
@@ -653,11 +649,12 @@ namespace System.Data {
                                //and ForeignKeys.\r
                                try\r
                                {\r
-                                       if (_table.DataSet == null || _table.DataSet.EnforceConstraints)\r
+                                       if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)\r
                                                _table.Rows.ValidateDataRowInternal(this);\r
                                }\r
                                catch (Exception e)\r
                                {\r
+                                       editing = false;\r
                                        proposed = null;\r
                                        throw e;\r
                                }\r
@@ -665,548 +662,562 @@ namespace System.Data {
                                CheckChildRows(DataRowAction.Change);\r
                                current = proposed;\r
                                proposed = null;\r
+                               editing = false;\r
                                _table.ChangedDataRow(this, DataRowAction.Change);\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the child rows of this DataRow using the specified DataRelation.\r
-               /// </summary>\r
-               public DataRow[] GetChildRows (DataRelation relation) \r
-               {\r
-                       return GetChildRows (relation, DataRowVersion.Current);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the child rows of a DataRow using the specified RelationName of a\r
-               /// DataRelation.\r
-               /// </summary>\r
-               public DataRow[] GetChildRows (string relationName) \r
-               {\r
-                       return GetChildRows (Table.DataSet.Relations[relationName]);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the child rows of a DataRow using the specified DataRelation, and\r
-               /// DataRowVersion.\r
-               /// </summary>\r
-               public DataRow[] GetChildRows (DataRelation relation, DataRowVersion version) \r
-               {\r
-                       if (relation == null)\r
-                               return new DataRow[0];\r
-\r
-                       if (this.Table == null)\r
-                               throw new RowNotInTableException();\r
-\r
-                       if (relation.DataSet != this.Table.DataSet)\r
-                               throw new ArgumentException();\r
-\r
-                       // TODO: Caching for better preformance\r
-                       ArrayList rows = new ArrayList();\r
-                       DataColumn[] parentColumns = relation.ParentColumns;\r
-                       DataColumn[] childColumns = relation.ChildColumns;\r
-                       int numColumn = parentColumns.Length;\r
-                       if (HasVersion(version)) \r
-                       {\r
-                               foreach (DataRow row in relation.ChildTable.Rows) \r
-                               {\r
-                                       bool allColumnsMatch = false;\r
-                                       if (row.HasVersion(DataRowVersion.Default))\r
-                                       {\r
-                                               allColumnsMatch = true;\r
-                                               for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) \r
-                                               {\r
-                                                       if (!this[parentColumns[columnCnt], version].Equals(\r
-                                                               row[childColumns[columnCnt], DataRowVersion.Default])) \r
-                                                       {\r
-                                                               allColumnsMatch = false;\r
-                                                               break;\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       if (allColumnsMatch) rows.Add(row);\r
-                               }\r
-                       }\r
-                       return rows.ToArray(typeof(DataRow)) as DataRow[];\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the child rows of a DataRow using the specified RelationName of a\r
-               /// DataRelation, and DataRowVersion.\r
-               /// </summary>\r
-               public DataRow[] GetChildRows (string relationName, DataRowVersion version) \r
-               {\r
-                       return GetChildRows (Table.DataSet.Relations[relationName], version);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the error description of the specified DataColumn.\r
-               /// </summary>\r
-               public string GetColumnError (DataColumn column) \r
-               {\r
-                       return GetColumnError (_table.Columns.IndexOf(column));\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the error description for the column specified by index.\r
-               /// </summary>\r
-               public string GetColumnError (int columnIndex) \r
-               {\r
-                       if (columnIndex < 0 || columnIndex >= columnErrors.Length)\r
-                               throw new IndexOutOfRangeException ();\r
-\r
-                       string retVal = columnErrors[columnIndex];\r
-                       if (retVal == null)\r
-                               retVal = string.Empty;\r
-                       return retVal;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the error description for the column, specified by name.\r
-               /// </summary>\r
-               public string GetColumnError (string columnName) \r
-               {\r
-                       return GetColumnError (_table.Columns.IndexOf(columnName));\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets an array of columns that have errors.\r
-               /// </summary>\r
-               public DataColumn[] GetColumnsInError () \r
-               {\r
-                       ArrayList dataColumns = new ArrayList ();\r
-\r
-                       for (int i = 0; i < columnErrors.Length; i += 1)\r
-                       {\r
-                               if (columnErrors[i] != null && columnErrors[i] != String.Empty)\r
-                                       dataColumns.Add (_table.Columns[i]);\r
-                       }\r
-\r
-                       return (DataColumn[])(dataColumns.ToArray (typeof(DataColumn)));\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the parent row of a DataRow using the specified DataRelation.\r
-               /// </summary>\r
-               public DataRow GetParentRow (DataRelation relation) \r
-               {\r
-                       return GetParentRow (relation, DataRowVersion.Current);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the parent row of a DataRow using the specified RelationName of a\r
-               /// DataRelation.\r
-               /// </summary>\r
-               public DataRow GetParentRow (string relationName) \r
-               {\r
-                       return GetParentRow (relationName, DataRowVersion.Current);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the parent row of a DataRow using the specified DataRelation, and\r
-               /// DataRowVersion.\r
-               /// </summary>\r
-               public DataRow GetParentRow (DataRelation relation, DataRowVersion version) \r
-               {\r
-                       DataRow[] rows = GetParentRows(relation, version);\r
-                       if (rows.Length == 0) return null;\r
-                       return rows[0];\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the parent row of a DataRow using the specified RelationName of a \r
-               /// DataRelation, and DataRowVersion.\r
-               /// </summary>\r
-               public DataRow GetParentRow (string relationName, DataRowVersion version) \r
-               {\r
-                       return GetParentRow (Table.DataSet.Relations[relationName], version);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the parent rows of a DataRow using the specified DataRelation.\r
-               /// </summary>\r
-               public DataRow[] GetParentRows (DataRelation relation) \r
-               {\r
-                       return GetParentRows (relation, DataRowVersion.Current);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the parent rows of a DataRow using the specified RelationName of a \r
-               /// DataRelation.\r
-               /// </summary>\r
-               public DataRow[] GetParentRows (string relationName) \r
-               {\r
-                       return GetParentRows (relationName, DataRowVersion.Current);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the parent rows of a DataRow using the specified DataRelation, and\r
-               /// DataRowVersion.\r
-               /// </summary>\r
-               public DataRow[] GetParentRows (DataRelation relation, DataRowVersion version) \r
-               {\r
-                       // TODO: Caching for better preformance\r
-                       if (relation == null)\r
-                               return new DataRow[0];\r
-\r
-                       if (this.Table == null)\r
-                               throw new RowNotInTableException();\r
-\r
-                       if (relation.DataSet != this.Table.DataSet)\r
-                               throw new ArgumentException();\r
-\r
-                       ArrayList rows = new ArrayList();\r
-                       DataColumn[] parentColumns = relation.ParentColumns;\r
-                       DataColumn[] childColumns = relation.ChildColumns;\r
-                       int numColumn = parentColumns.Length;\r
-                       if (HasVersion(version))\r
-                       {\r
-                               foreach (DataRow row in relation.ParentTable.Rows) \r
-                               {\r
-                                       bool allColumnsMatch = false;\r
-                                       if (row.HasVersion(DataRowVersion.Default))\r
-                                       {\r
-                                               allColumnsMatch = true;\r
-                                               for (int columnCnt = 0; columnCnt < numColumn; columnCnt++) \r
-                                               {\r
-                                                       if (!this[childColumns[columnCnt], version].Equals(\r
-                                                               row[parentColumns[columnCnt], DataRowVersion.Default])) \r
-                                                       {\r
-                                                               allColumnsMatch = false;\r
-                                                               break;\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       if (allColumnsMatch) rows.Add(row);\r
-                               }\r
-                       }\r
-                       return rows.ToArray(typeof(DataRow)) as DataRow[];\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets the parent rows of a DataRow using the specified RelationName of a \r
-               /// DataRelation, and DataRowVersion.\r
-               /// </summary>\r
-               public DataRow[] GetParentRows (string relationName, DataRowVersion version) \r
-               {\r
-                       return GetParentRows (Table.DataSet.Relations[relationName], version);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets a value indicating whether a specified version exists.\r
-               /// </summary>\r
-               public bool HasVersion (DataRowVersion version) \r
-               {\r
-                       switch (version)\r
-                       {\r
-                               case DataRowVersion.Default:\r
-                                       if (rowState == DataRowState.Deleted)\r
-                                               return false;\r
-                                       if (rowState == DataRowState.Detached)\r
-                                               return proposed != null;\r
-                                       return true;\r
-                               case DataRowVersion.Proposed:\r
-                                       if (rowState == DataRowState.Deleted)\r
-                                               return false;\r
-                                       return (proposed != null);\r
-                               case DataRowVersion.Current:\r
-                                       if (rowState == DataRowState.Deleted || rowState == DataRowState.Detached)\r
-                                               return false;\r
-                                       return (current != null);\r
-                               case DataRowVersion.Original:\r
-                                       if (rowState == DataRowState.Detached)\r
-                                               return false;\r
-                                       return (original != null);\r
-                       }\r
-                       return false;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets a value indicating whether the specified DataColumn contains a null value.\r
-               /// </summary>\r
-               public bool IsNull (DataColumn column) \r
-               {\r
-                       object o = this[column];\r
-                       return (o == null || o == DBNull.Value);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets a value indicating whether the column at the specified index contains a null\r
-               /// value.\r
-               /// </summary>\r
-               public bool IsNull (int columnIndex) \r
-               {\r
-                       object o = this[columnIndex];\r
-                       return (o == null || o == DBNull.Value);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets a value indicating whether the named column contains a null value.\r
-               /// </summary>\r
-               public bool IsNull (string columnName) \r
-               {\r
-                       object o = this[columnName];\r
-                       return (o == null || o == DBNull.Value);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets a value indicating whether the specified DataColumn and DataRowVersion\r
-               /// contains a null value.\r
-               /// </summary>\r
-               public bool IsNull (DataColumn column, DataRowVersion version) \r
-               {\r
-                       object o = this[column, version];\r
-                       return (o == null || o == DBNull.Value);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Rejects all changes made to the row since AcceptChanges was last called.\r
-               /// </summary>\r
-               public void RejectChanges () \r
-               {\r
-                       // If original is null, then nothing has happened since AcceptChanges\r
-                       // was last called.  We have no "original" to go back to.\r
-                       if (original != null)\r
-                       {\r
-                               Array.Copy (original, current, _table.Columns.Count);\r
-                              \r
-                               _table.ChangedDataRow (this, DataRowAction.Rollback);\r
-                               CancelEdit ();\r
-                               switch (rowState)\r
-                               {\r
-                                       case DataRowState.Added:\r
-                                               _table.Rows.Remove (this);\r
-                                               break;\r
-                                       case DataRowState.Modified:\r
-                                               rowState = DataRowState.Unchanged;\r
-                                               break;\r
-                                       case DataRowState.Deleted:\r
-                                               rowState = DataRowState.Unchanged;\r
-                                               break;\r
-                               } \r
-                               \r
-                       }                       \r
-                       else {\r
-                               // If rows are just loaded via Xml the original values are null.\r
-                               // So in this case we have to remove all columns.\r
-                               // FIXME: I'm not realy sure, does this break something else, but\r
-                               // if so: FIXME ;)\r
-                               \r
-                               if ((rowState & DataRowState.Added) > 0)\r
-                                       _table.Rows.Remove (this);\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Sets the error description for a column specified as a DataColumn.\r
-               /// </summary>\r
-               public void SetColumnError (DataColumn column, string error) \r
-               {\r
-                       SetColumnError (_table.Columns.IndexOf (column), error);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Sets the error description for a column specified by index.\r
-               /// </summary>\r
-               public void SetColumnError (int columnIndex, string error) \r
-               {\r
-                       if (columnIndex < 0 || columnIndex >= columnErrors.Length)\r
-                               throw new IndexOutOfRangeException ();\r
-                       columnErrors[columnIndex] = error;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Sets the error description for a column specified by name.\r
-               /// </summary>\r
-               public void SetColumnError (string columnName, string error) \r
+                       }
+               }
+
+               /// <summary>
+               /// Gets the child rows of this DataRow using the specified DataRelation.
+               /// </summary>
+               public DataRow[] GetChildRows (DataRelation relation) 
+               {
+                       return GetChildRows (relation, DataRowVersion.Current);
+               }
+
+               /// <summary>
+               /// Gets the child rows of a DataRow using the specified RelationName of a
+               /// DataRelation.
+               /// </summary>
+               public DataRow[] GetChildRows (string relationName) 
+               {
+                       return GetChildRows (Table.DataSet.Relations[relationName]);
+               }
+
+               /// <summary>
+               /// Gets the child rows of a DataRow using the specified DataRelation, and
+               /// DataRowVersion.
+               /// </summary>
+               public DataRow[] GetChildRows (DataRelation relation, DataRowVersion version) 
+               {
+                       if (relation == null)
+                               return new DataRow[0];
+
+                       if (this.Table == null)
+                               throw new RowNotInTableException();
+
+                       if (relation.DataSet != this.Table.DataSet)
+                               throw new ArgumentException();
+
+                       // TODO: Caching for better preformance
+                       ArrayList rows = new ArrayList();
+                       DataColumn[] parentColumns = relation.ParentColumns;
+                       DataColumn[] childColumns = relation.ChildColumns;
+                       int numColumn = parentColumns.Length;
+                       if (HasVersion(version)) 
+                       {
+                               foreach (DataRow row in relation.ChildTable.Rows) 
+                               {
+                                       bool allColumnsMatch = false;
+                                       if (row.HasVersion(DataRowVersion.Default))
+                                       {
+                                               allColumnsMatch = true;
+                                               for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) 
+                                               {
+                                                       if (!this[parentColumns[columnCnt], version].Equals(
+                                                               row[childColumns[columnCnt], DataRowVersion.Default])) 
+                                                       {
+                                                               allColumnsMatch = false;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       if (allColumnsMatch) rows.Add(row);
+                               }
+                       }
+                       return rows.ToArray(typeof(DataRow)) as DataRow[];
+               }
+
+               /// <summary>
+               /// Gets the child rows of a DataRow using the specified RelationName of a
+               /// DataRelation, and DataRowVersion.
+               /// </summary>
+               public DataRow[] GetChildRows (string relationName, DataRowVersion version) 
+               {
+                       return GetChildRows (Table.DataSet.Relations[relationName], version);
+               }
+
+               /// <summary>
+               /// Gets the error description of the specified DataColumn.
+               /// </summary>
+               public string GetColumnError (DataColumn column) 
+               {
+                       return GetColumnError (_table.Columns.IndexOf(column));
+               }
+
+               /// <summary>
+               /// Gets the error description for the column specified by index.
+               /// </summary>
+               public string GetColumnError (int columnIndex) 
+               {
+                       if (columnIndex < 0 || columnIndex >= columnErrors.Length)
+                               throw new IndexOutOfRangeException ();
+
+                       string retVal = columnErrors[columnIndex];
+                       if (retVal == null)
+                               retVal = string.Empty;
+                       return retVal;
+               }
+
+               /// <summary>
+               /// Gets the error description for the column, specified by name.
+               /// </summary>
+               public string GetColumnError (string columnName) 
+               {
+                       return GetColumnError (_table.Columns.IndexOf(columnName));
+               }
+
+               /// <summary>
+               /// Gets an array of columns that have errors.
+               /// </summary>
+               public DataColumn[] GetColumnsInError () 
+               {
+                       ArrayList dataColumns = new ArrayList ();
+
+                       for (int i = 0; i < columnErrors.Length; i += 1)
+                       {
+                               if (columnErrors[i] != null && columnErrors[i] != String.Empty)
+                                       dataColumns.Add (_table.Columns[i]);
+                       }
+
+                       return (DataColumn[])(dataColumns.ToArray (typeof(DataColumn)));
+               }
+
+               /// <summary>
+               /// Gets the parent row of a DataRow using the specified DataRelation.
+               /// </summary>
+               public DataRow GetParentRow (DataRelation relation) 
+               {
+                       return GetParentRow (relation, DataRowVersion.Current);
+               }
+
+               /// <summary>
+               /// Gets the parent row of a DataRow using the specified RelationName of a
+               /// DataRelation.
+               /// </summary>
+               public DataRow GetParentRow (string relationName) 
+               {
+                       return GetParentRow (relationName, DataRowVersion.Current);
+               }
+
+               /// <summary>
+               /// Gets the parent row of a DataRow using the specified DataRelation, and
+               /// DataRowVersion.
+               /// </summary>
+               public DataRow GetParentRow (DataRelation relation, DataRowVersion version) 
+               {
+                       DataRow[] rows = GetParentRows(relation, version);
+                       if (rows.Length == 0) return null;
+                       return rows[0];
+               }
+
+               /// <summary>
+               /// Gets the parent row of a DataRow using the specified RelationName of a 
+               /// DataRelation, and DataRowVersion.
+               /// </summary>
+               public DataRow GetParentRow (string relationName, DataRowVersion version) 
+               {
+                       return GetParentRow (Table.DataSet.Relations[relationName], version);
+               }
+
+               /// <summary>
+               /// Gets the parent rows of a DataRow using the specified DataRelation.
+               /// </summary>
+               public DataRow[] GetParentRows (DataRelation relation) 
+               {
+                       return GetParentRows (relation, DataRowVersion.Current);
+               }
+
+               /// <summary>
+               /// Gets the parent rows of a DataRow using the specified RelationName of a 
+               /// DataRelation.
+               /// </summary>
+               public DataRow[] GetParentRows (string relationName) 
+               {
+                       return GetParentRows (relationName, DataRowVersion.Current);
+               }
+
+               /// <summary>
+               /// Gets the parent rows of a DataRow using the specified DataRelation, and
+               /// DataRowVersion.
+               /// </summary>
+               public DataRow[] GetParentRows (DataRelation relation, DataRowVersion version) 
+               {
+                       // TODO: Caching for better preformance
+                       if (relation == null)
+                               return new DataRow[0];
+
+                       if (this.Table == null)
+                               throw new RowNotInTableException();
+
+                       if (relation.DataSet != this.Table.DataSet)
+                               throw new ArgumentException();
+
+                       ArrayList rows = new ArrayList();
+                       DataColumn[] parentColumns = relation.ParentColumns;
+                       DataColumn[] childColumns = relation.ChildColumns;
+                       int numColumn = parentColumns.Length;
+                       if (HasVersion(version))
+                       {
+                               foreach (DataRow row in relation.ParentTable.Rows) 
+                               {
+                                       bool allColumnsMatch = false;
+                                       if (row.HasVersion(DataRowVersion.Default))
+                                       {
+                                               allColumnsMatch = true;
+                                               for (int columnCnt = 0; columnCnt < numColumn; columnCnt++) 
+                                               {
+                                                       if (!this[childColumns[columnCnt], version].Equals(
+                                                               row[parentColumns[columnCnt], DataRowVersion.Default])) 
+                                                       {
+                                                               allColumnsMatch = false;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       if (allColumnsMatch) rows.Add(row);
+                               }
+                       }
+                       return rows.ToArray(typeof(DataRow)) as DataRow[];
+               }
+
+               /// <summary>
+               /// Gets the parent rows of a DataRow using the specified RelationName of a 
+               /// DataRelation, and DataRowVersion.
+               /// </summary>
+               public DataRow[] GetParentRows (string relationName, DataRowVersion version) 
+               {
+                       return GetParentRows (Table.DataSet.Relations[relationName], version);
+               }
+
+               /// <summary>
+               /// Gets a value indicating whether a specified version exists.
+               /// </summary>
+               public bool HasVersion (DataRowVersion version) 
+               {
+                       switch (version)
+                       {
+                               case DataRowVersion.Default:
+                                       if (rowState == DataRowState.Deleted)
+                                               return false;
+                                       if (rowState == DataRowState.Detached)
+                                               return proposed != null;
+                                       return true;
+                               case DataRowVersion.Proposed:
+                                       if (rowState == DataRowState.Deleted)
+                                               return false;
+                                       return (proposed != null);
+                               case DataRowVersion.Current:
+                                       if (rowState == DataRowState.Deleted || rowState == DataRowState.Detached)
+                                               return false;
+                                       return (current != null);
+                               case DataRowVersion.Original:
+                                       if (rowState == DataRowState.Detached)
+                                               return false;
+                                       return (original != null);
+                       }
+                       return false;
+               }
+
+               /// <summary>
+               /// Gets a value indicating whether the specified DataColumn contains a null value.
+               /// </summary>
+               public bool IsNull (DataColumn column) 
+               {
+                       object o = this[column];
+                       return (o == null || o == DBNull.Value);
+               }
+
+               /// <summary>
+               /// Gets a value indicating whether the column at the specified index contains a null
+               /// value.
+               /// </summary>
+               public bool IsNull (int columnIndex) 
+               {
+                       object o = this[columnIndex];
+                       return (o == null || o == DBNull.Value);
+               }
+
+               /// <summary>
+               /// Gets a value indicating whether the named column contains a null value.
+               /// </summary>
+               public bool IsNull (string columnName) 
+               {
+                       object o = this[columnName];
+                       return (o == null || o == DBNull.Value);
+               }
+
+               /// <summary>
+               /// Gets a value indicating whether the specified DataColumn and DataRowVersion
+               /// contains a null value.
+               /// </summary>
+               public bool IsNull (DataColumn column, DataRowVersion version) 
+               {
+                       object o = this[column, version];
+                       return (o == null || o == DBNull.Value);
+               }
+
+               /// <summary>
+               /// Rejects all changes made to the row since AcceptChanges was last called.
+               /// </summary>
+               public void RejectChanges () 
+               {
+                       // If original is null, then nothing has happened since AcceptChanges
+                       // was last called.  We have no "original" to go back to.
+                       if (original != null)
+                       {
+                               Array.Copy (original, current, _table.Columns.Count);
+                              
+                               _table.ChangedDataRow (this, DataRowAction.Rollback);
+                               CancelEdit ();
+                               switch (rowState)
+                               {
+                                       case DataRowState.Added:
+                                               _table.Rows.Remove (this);
+                                               break;
+                                       case DataRowState.Modified:
+                                               rowState = DataRowState.Unchanged;
+                                               break;
+                                       case DataRowState.Deleted:
+                                               rowState = DataRowState.Unchanged;
+                                               break;
+                               } 
+                               
+                       }                       
+                       else {
+                               // If rows are just loaded via Xml the original values are null.
+                               // So in this case we have to remove all columns.
+                               // FIXME: I'm not realy sure, does this break something else, but
+                               // if so: FIXME ;)
+                               
+                               if ((rowState & DataRowState.Added) > 0)
+                                       _table.Rows.Remove (this);
+                       }
+               }
+
+               /// <summary>
+               /// Sets the error description for a column specified as a DataColumn.
+               /// </summary>
+               public void SetColumnError (DataColumn column, string error) 
+               {
+                       SetColumnError (_table.Columns.IndexOf (column), error);
+               }
+
+               /// <summary>
+               /// Sets the error description for a column specified by index.
+               /// </summary>
+               public void SetColumnError (int columnIndex, string error) 
+               {
+                       if (columnIndex < 0 || columnIndex >= columnErrors.Length)
+                               throw new IndexOutOfRangeException ();
+                       columnErrors[columnIndex] = error;
+               }
+
+               /// <summary>
+               /// Sets the error description for a column specified by name.
+               /// </summary>
+               public void SetColumnError (string columnName, string error) 
+               {
+                       SetColumnError (_table.Columns.IndexOf (columnName), error);
+               }
+
+               /// <summary>
+               /// Sets the value of the specified DataColumn to a null value.
+               /// </summary>
+               protected void SetNull (DataColumn column) 
+               {
+                       this[column] = DBNull.Value;
+               }
+
+               /// <summary>
+               /// Sets the parent row of a DataRow with specified new parent DataRow.
+               /// </summary>
+               [MonoTODO]
+               public void SetParentRow (DataRow parentRow) 
+               {
+                       SetParentRow(parentRow, null);
+               }
+
+               /// <summary>
+               /// Sets the parent row of a DataRow with specified new parent DataRow and
+               /// DataRelation.
+               /// </summary>
+               [MonoTODO]
+               public void SetParentRow (DataRow parentRow, DataRelation relation) 
+               {
+                       if (_table == null || parentRow.Table == null)
+                               throw new RowNotInTableException();
+
+                       if (parentRow != null && _table.DataSet != parentRow.Table.DataSet)
+                               throw new ArgumentException();
+                       
+                       BeginEdit();
+                       if (relation == null)
+                       {
+                               foreach (DataRelation parentRel in _table.ParentRelations)
+                               {
+                                       DataColumn[] childCols = parentRel.ChildKeyConstraint.Columns;
+                                       DataColumn[] parentCols = parentRel.ChildKeyConstraint.RelatedColumns;
+                                       
+                                       for (int i = 0; i < parentCols.Length; i++)
+                                       {
+                                               if (parentRow == null)
+                                                       this[childCols[i].Ordinal] = DBNull.Value;
+                                               else
+                                                       this[childCols[i].Ordinal] = parentRow[parentCols[i]];
+                                       }
+                                       
+                               }
+                       }
+                       else
+                       {
+                               DataColumn[] childCols = relation.ChildKeyConstraint.Columns;
+                               DataColumn[] parentCols = relation.ChildKeyConstraint.RelatedColumns;
+                                       
+                               for (int i = 0; i < parentCols.Length; i++)
+                               {
+                                       if (parentRow == null)
+                                               this[childCols[i].Ordinal] = DBNull.Value;
+                                       else
+                                               this[childCols[i].Ordinal] = parentRow[parentCols[i]];
+                               }
+                       }
+                       EndEdit();
+               }
+               
+               //Copy all values of this DataaRow to the row parameter.
+               internal void CopyValuesToRow(DataRow row)
+               {
+                                               
+                       if (row == null)
+                               throw new ArgumentNullException("row");
+                       if (row == this)
+                               throw new ArgumentException("'row' is the same as this object");
+
+                       DataColumnCollection columns = Table.Columns;
+                       
+                       for(int i = 0; i < columns.Count; i++){
+
+                               string columnName = columns[i].ColumnName;
+                               int index = row.Table.Columns.IndexOf(columnName);
+                               //if a column with the same name exists in both rows copy the values
+                               if(index != -1) {
+                                       if (HasVersion(DataRowVersion.Original))
+                                       {
+                                               if (row.original == null)
+                                                       row.original = new object[row.Table.Columns.Count];
+                                               row.original[index] = row.SetColumnValue(original[i], index);
+                                       }
+                                       if (HasVersion(DataRowVersion.Current))
+                                       {
+                                               if (row.current == null)
+                                                       row.current = new object[row.Table.Columns.Count];
+                                               row.current[index] = row.SetColumnValue(current[i], index);
+                                       }
+                                       if (HasVersion(DataRowVersion.Proposed))
+                                       {
+                                               if (row.proposed == null)
+                                                       row.proposed = new object[row.Table.Columns.Count];
+                                               row.proposed[index] = row.SetColumnValue(proposed[i], index);
+                                       }
+                                       
+                                       //Saving the current value as the column value
+                                       row[index] = row.current[index];
+                                       
+                               }
+                       }
+
+                       row.rowState = RowState;
+                       row.RowError = RowError;
+                       row.columnErrors = columnErrors;
+               }
+
+               
+               public void CollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs args)
+               {
+                       // if a column is added we hava to add an additional value the 
+                       // the priginal, current and propoed arrays.
+                       // this scenario can happened in merge operation.
+
+                       if (args.Action == System.ComponentModel.CollectionChangeAction.Add)
+                       {
+                               object[] tmp;
+                               if (current != null)
+                               {
+                                       tmp = new object[current.Length + 1];
+                                       Array.Copy (current, tmp, current.Length);
+                                       tmp[tmp.Length - 1] = DBNull.Value;
+                                       current = tmp;
+                               }
+                               if (proposed != null)
+                               {
+                                       tmp = new object[proposed.Length + 1];
+                                       Array.Copy (proposed, tmp, proposed.Length);
+                                       tmp[tmp.Length - 1] = DBNull.Value;
+                                       proposed = tmp;
+                               }
+                               if(original != null)
+                               {
+                                       tmp = new object[original.Length + 1];
+                                       Array.Copy (original, tmp, original.Length);
+                                       tmp[tmp.Length - 1] = DBNull.Value;
+                                       original = tmp;
+                               }
+
+                       }
+               }
+
+               internal bool IsRowChanged(DataRowState rowState) {
+                       if((RowState & rowState) != 0)
+                               return true;
+
+                       //we need to find if child rows of this row changed.
+                       //if yes - we should return true
+
+                       // if the rowState is deleted we should get the original version of the row
+                       // else - we should get the current version of the row.
+                       DataRowVersion version = (rowState == DataRowState.Deleted) ? DataRowVersion.Original : DataRowVersion.Current;
+                       int count = Table.ChildRelations.Count;
+                       for (int i = 0; i < count; i++){
+                               DataRelation rel = Table.ChildRelations[i];
+                               DataRow[] childRows = GetChildRows(rel, version);
+                               for (int j = 0; j < childRows.Length; j++){
+                                       if (childRows[j].IsRowChanged(rowState))
+                                               return true;
+                               }
+                       }
+
+                       return false;
+               }
+
+               internal bool HasParentCollection
+               {
+                       get
+                       {
+                               return _hasParentCollection;
+                       }
+                       set
+                       {
+                               _hasParentCollection = value;
+                       }
+               }
+
+               internal void CheckNullConstraints()\r
                {\r
-                       SetColumnError (_table.Columns.IndexOf (columnName), error);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Sets the value of the specified DataColumn to a null value.\r
-               /// </summary>\r
-               protected void SetNull (DataColumn column) \r
-               {\r
-                       this[column] = DBNull.Value;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Sets the parent row of a DataRow with specified new parent DataRow.\r
-               /// </summary>\r
-               [MonoTODO]\r
-               public void SetParentRow (DataRow parentRow) \r
-               {\r
-                       SetParentRow(parentRow, null);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Sets the parent row of a DataRow with specified new parent DataRow and\r
-               /// DataRelation.\r
-               /// </summary>\r
-               [MonoTODO]\r
-               public void SetParentRow (DataRow parentRow, DataRelation relation) \r
-               {\r
-                       if (_table == null || parentRow.Table == null)\r
-                               throw new RowNotInTableException();\r
-\r
-                       if (parentRow != null && _table.DataSet != parentRow.Table.DataSet)\r
-                               throw new ArgumentException();\r
-                       \r
-                       BeginEdit();\r
-                       if (relation == null)\r
+                       if (_nullConstraintViolation)\r
                        {\r
-                               foreach (DataRelation parentRel in _table.ParentRelations)\r
+                               for (int i = 0; i < proposed.Length; i++)\r
                                {\r
-                                       DataColumn[] childCols = parentRel.ChildKeyConstraint.Columns;\r
-                                       DataColumn[] parentCols = parentRel.ChildKeyConstraint.RelatedColumns;\r
-                                       \r
-                                       for (int i = 0; i < parentCols.Length; i++)\r
-                                       {\r
-                                               if (parentRow == null)\r
-                                                       this[childCols[i].Ordinal] = DBNull.Value;\r
-                                               else\r
-                                                       this[childCols[i].Ordinal] = parentRow[parentCols[i]];\r
-                                       }\r
-                                       \r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               DataColumn[] childCols = relation.ChildKeyConstraint.Columns;\r
-                               DataColumn[] parentCols = relation.ChildKeyConstraint.RelatedColumns;\r
-                                       \r
-                               for (int i = 0; i < parentCols.Length; i++)\r
-                               {\r
-                                       if (parentRow == null)\r
-                                               this[childCols[i].Ordinal] = DBNull.Value;\r
-                                       else\r
-                                               this[childCols[i].Ordinal] = parentRow[parentCols[i]];\r
+                                       if (this[i] == DBNull.Value && !_table.Columns[i].AllowDBNull)\r
+                                               throw new NoNullAllowedException(_nullConstraintMessage);\r
                                }\r
+                               _nullConstraintViolation = false;\r
                        }\r
-                       EndEdit();\r
-               }\r
-               \r
-               //Copy all values of this DataaRow to the row parameter.\r
-               internal void CopyValuesToRow(DataRow row)\r
-               {\r
-                                               \r
-                       if (row == null)\r
-                               throw new ArgumentNullException("row");\r
-                       if (row == this)\r
-                               throw new ArgumentException("'row' is the same as this object");\r
-\r
-                       DataColumnCollection columns = Table.Columns;\r
-                       \r
-                       for(int i = 0; i < columns.Count; i++){\r
-\r
-                               string columnName = columns[i].ColumnName;\r
-                               int index = row.Table.Columns.IndexOf(columnName);\r
-                               //if a column with the same name exists in both rows copy the values\r
-                               if(index != -1) {\r
-                                       if (HasVersion(DataRowVersion.Original))\r
-                                       {\r
-                                               if (row.original == null)\r
-                                                       row.original = new object[row.Table.Columns.Count];\r
-                                               row.original[index] = row.SetColumnValue(original[i], index);\r
-                                       }\r
-                                       if (HasVersion(DataRowVersion.Current))\r
-                                       {\r
-                                               if (row.current == null)\r
-                                                       row.current = new object[row.Table.Columns.Count];\r
-                                               row.current[index] = row.SetColumnValue(current[i], index);\r
-                                       }\r
-                                       if (HasVersion(DataRowVersion.Proposed))\r
-                                       {\r
-                                               if (row.proposed == null)\r
-                                                       row.proposed = new object[row.Table.Columns.Count];\r
-                                               row.proposed[index] = row.SetColumnValue(proposed[i], index);\r
-                                       }\r
-                                       \r
-                                       //Saving the current value as the column value\r
-                                       row[index] = row.current[index];\r
-                                       \r
-                               }\r
-                       }\r
-\r
-                       row.rowState = RowState;\r
-                       row.RowError = RowError;\r
-                       row.columnErrors = columnErrors;\r
-               }\r
-\r
-               \r
-               public void CollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs args)\r
-               {\r
-                       // if a column is added we hava to add an additional value the \r
-                       // the priginal, current and propoed arrays.\r
-                       // this scenario can happened in merge operation.\r
-\r
-                       if (args.Action == System.ComponentModel.CollectionChangeAction.Add)\r
-                       {\r
-                               object[] tmp;\r
-                               if (current != null)\r
-                               {\r
-                                       tmp = new object[current.Length + 1];\r
-                                       Array.Copy (current, tmp, current.Length);\r
-                                       tmp[tmp.Length - 1] = DBNull.Value;\r
-                                       current = tmp;\r
-                               }\r
-                               if (proposed != null)\r
-                               {\r
-                                       tmp = new object[proposed.Length + 1];\r
-                                       Array.Copy (proposed, tmp, proposed.Length);\r
-                                       tmp[tmp.Length - 1] = DBNull.Value;\r
-                                       proposed = tmp;\r
-                               }\r
-                               if(original != null)\r
-                               {\r
-                                       tmp = new object[original.Length + 1];\r
-                                       Array.Copy (original, tmp, original.Length);\r
-                                       tmp[tmp.Length - 1] = DBNull.Value;\r
-                                       original = tmp;\r
-                               }\r
-\r
-                       }\r
-               }\r
-\r
-               internal bool IsRowChanged(DataRowState rowState) {\r
-                       if((RowState & rowState) != 0)\r
-                               return true;\r
-\r
-                       //we need to find if child rows of this row changed.\r
-                       //if yes - we should return true\r
-\r
-                       // if the rowState is deleted we should get the original version of the row\r
-                       // else - we should get the current version of the row.\r
-                       DataRowVersion version = (rowState == DataRowState.Deleted) ? DataRowVersion.Original : DataRowVersion.Current;\r
-                       int count = Table.ChildRelations.Count;\r
-                       for (int i = 0; i < count; i++){\r
-                               DataRelation rel = Table.ChildRelations[i];\r
-                               DataRow[] childRows = GetChildRows(rel, version);\r
-                               for (int j = 0; j < childRows.Length; j++){\r
-                                       if (childRows[j].IsRowChanged(rowState))\r
-                                               return true;\r
-                               }\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-               internal bool HasParentCollection\r
-               {\r
-                       get\r
-                       {\r
-                               return _hasParentCollection;\r
-                       }\r
-                       set\r
-                       {\r
-                               _hasParentCollection = value;\r
-                       }\r
-               }\r
-\r
-               #endregion // Methods\r
-       }\r
-\r
-       \r
-\r
-}\r
+               }
+
+               #endregion // Methods
+       }
+
+       
+
+}
index 7c261db985f2f18538c627dd7af05fd11f797452..dd7eebe611fd1e31e383584354c664a86e6ab1fb 100644 (file)
@@ -155,7 +155,7 @@ namespace System.Data
                                if (row.RowState != DataRowState.Deleted)
                                {
                                        object primValue = row [primColumnName];
-                                       if (key == null) \r
+                                       if (key == null) 
                                        {
                                                if (primValue == null)
                                                        return row;
@@ -196,12 +196,12 @@ namespace System.Data
                                if (row.RowState != DataRowState.Deleted)
                                {
                                        bool eq = true;
-                                       for (int i = 0; i < keys.Length; i++) \r
+                                       for (int i = 0; i < keys.Length; i++) 
                                        {
                                        
                                                object primValue = row [primColumnNames [i]];
                                                object keyValue = keys [i];
-                                               if (keyValue == null) \r
+                                               if (keyValue == null) 
                                                {
                                                        if (primValue == null)
                                                                return row;
@@ -211,7 +211,7 @@ namespace System.Data
                                                                       
                                                newKey = Convert.ChangeType (keyValue, Type.GetTypeCode(primValue.GetType ()));
 
-                                               if (!primValue.Equals (newKey)) \r
+                                               if (!primValue.Equals (newKey)) 
                                                {
                                                        eq = false;
                                                        break;
@@ -276,6 +276,8 @@ namespace System.Data
                [MonoTODO]
                internal void ValidateDataRowInternal(DataRow row)
                {
+                       //first check for null violations.
+                       row.CheckNullConstraints();
                        //FIXME: this validates constraints in the order they appear
                        //in the collection. Most probably we need to do it in a 
                        //specific order like unique/primary keys first, then Foreignkeys, etc
index 9c05fadbd1bfb5f912601dcd3d922c0e69ff54b5..317aade0a1161e842e8a09ea0f5bd5619d8d0cd0 100644 (file)
@@ -82,6 +82,14 @@ namespace System.Data {
                                }
 
                                caseSensitive = value; 
+                               if (!caseSensitive)
+                               {
+                                       foreach (DataTable table in Tables)
+                                       {
+                                               foreach (Constraint c in table.Constraints)
+                                                       c.AssertConstraint();
+                                       }
+                               }
                        }
                }
 
@@ -107,7 +115,20 @@ namespace System.Data {
                [DefaultValue (true)]
                public bool EnforceConstraints {
                        get { return enforceConstraints; } 
-                       set { enforceConstraints = value; }
+                       set { 
+                               if (value != enforceConstraints)
+                               {
+                                       enforceConstraints = value; 
+                                       if (value)
+                                       {
+                                               foreach (DataTable table in Tables)
+                                               {
+                                                       foreach (Constraint c in table.Constraints)
+                                                               c.AssertConstraint();
+                                               }
+                                       }
+                               }
+                       }
                }
 
                [Browsable (false)]
@@ -791,12 +812,10 @@ namespace System.Data {
                #region ISupportInitialize methods
                public void BeginInit ()
                {
-                       throw new NotImplementedException ();
                }
                
                public void EndInit ()
                {
-                       throw new NotImplementedException ();
                }
                #endregion
 
index e8d28cf1213636e597960aede1c73d172df0a842..4af1b9fffd7b3090424a2cb189289bd5b47c1390 100644 (file)
@@ -359,7 +359,9 @@ namespace System.Data {
                        
                        //Unique?       
                        DataTable tbl = _dataTable;
-
+                       bool ignoreCase = false;
+                       if (_dataTable.DataSet != null)
+                               ignoreCase = !_dataTable.DataSet.CaseSensitive;
                        //TODO: Investigate other ways of speeding up the validation work below.
 
                        //validate no duplicates exists.
@@ -371,20 +373,31 @@ namespace System.Data {
                                DataRow[] rows = new DataRow [tbl.Rows.Count];
                                tbl.Rows.CopyTo (rows, 0);
                                
-                               Array.Sort(rows, new RowsComparer(this));
+                               Array.Sort(rows, new RowsComparer(this, ignoreCase));
+                               
                                for (int i = 0 ; i < rows.Length - 1 ; i++) 
-                               {\r
-                                       bool match = true;\r
-                                       // check if the values in the constraints columns are equal\r
-                                       for (int j = 0; j < _dataColumns.Length; j++)\r
-                                       {\r
-                                               if (!rows[i][_dataColumns[j]].Equals(rows[i + 1][_dataColumns[j]]))\r
-                                               {\r
-                                                       match = false;\r
-                                                       break;\r
-                                               }       \r
-                                       }\r
-                                       if (match)\r
+                               {
+                                       bool match = true;
+                                       // check if the values in the constraints columns are equal
+                                       for (int j = 0; j < _dataColumns.Length; j++)
+                                       {
+                                               if (_dataColumns[j].DataType == typeof(string))
+                                               {
+                                                       string origVal = (string)rows[i][_dataColumns[j]];
+                                                       string compVal = (string)rows[i + 1][_dataColumns[j]];
+                                                       if (String.Compare(origVal, compVal, ignoreCase) != 0)
+                                                       {
+                                                               match = false;
+                                                               break;
+                                                       }
+                                               }
+                                               else if (!rows[i][_dataColumns[j]].Equals(rows[i + 1][_dataColumns[j]]))
+                                               {
+                                                       match = false;
+                                                       break;
+                                               }       
+                                       }
+                                       if (match)
                                                throw new ConstraintException (String.Format ("Column '{0}' contains non-unique values", this._dataColumns[0]));                                        
                                }
                        }
@@ -420,6 +433,10 @@ namespace System.Data {
                                        rowVals[i] = row[_dataColumns[i], DataRowVersion.Current];
                        }
                        
+                       bool ignoreCase = false;
+                       if (_dataTable.DataSet != null)
+                               ignoreCase = !_dataTable.DataSet.CaseSensitive;
+
                        foreach(DataRow compareRow in tbl.Rows)
                        {
                                if (compareRow.RowState != DataRowState.Deleted)
@@ -428,13 +445,21 @@ namespace System.Data {
                                        //skip if it is the same row to be validated
                                        if(!row.Equals(compareRow))
                                        {
-                                               //FIXME: should we compare to compareRow[DataRowVersion.Current]?
-                                               //FIXME: We need to compare to all columns the constraint is set to.
                                                for (int i = 0; i < _dataColumns.Length; i++)
                                                {
                                                        // if the values in the row are not equal to the values of
                                                        // the original row from the table we can move to the next row.
-                                                       if(!rowVals[i].Equals( compareRow[_dataColumns[i]]))
+                                                       if (_dataColumns[i].DataType == typeof(string))
+                                                       {
+                                                               string origVal = (string)rowVals[i];
+                                                               string compVal = (string)compareRow[_dataColumns[i]];
+                                                               if (String.Compare(origVal, compVal, ignoreCase) != 0)
+                                                               {
+                                                                       isValid = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                                       else if (!rowVals[i].Equals( compareRow[_dataColumns[i]]))
                                                        {
                                                                isValid = true;
                                                                break;
@@ -467,15 +492,24 @@ namespace System.Data {
                }
                
                // generates a hash key for a given row based on the constraints columns.
-               internal int CalcHashValue(DataRow row)
+               internal int CalcHashValue(DataRow row, bool ignoreCase)
                {
                        object o;
                        int retVal = 0;
+                       CaseInsensitiveHashCodeProvider ciProvider = null;
+                       if (ignoreCase)
+                               ciProvider = new CaseInsensitiveHashCodeProvider(_dataTable.Locale);
                        for (int i = 0; i < _dataColumns.Length; i++)
                        {
                                o = row[_dataColumns[i]];
                                if (o != null)
-                                       retVal += o.GetHashCode();
+                               {
+                                       if (ciProvider != null)
+                                               retVal += ciProvider.GetHashCode(o);
+                                       else
+                                               retVal += o.GetHashCode();
+
+                               }
                        }
                        return retVal;
                }
@@ -485,9 +519,11 @@ namespace System.Data {
                private class RowsComparer : IComparer
                {
                        private UniqueConstraint _uc;
+                       private bool _ignoreCase;
                        
-                       public RowsComparer(UniqueConstraint uc)
+                       public RowsComparer(UniqueConstraint uc, bool ignoreCase)
                        {
+                               _ignoreCase = ignoreCase;
                                _uc = uc;
                        }
 
@@ -495,10 +531,14 @@ namespace System.Data {
                        {
                                DataRow row1 = (DataRow) o1;
                                DataRow row2 = (DataRow) o2;
-                               int val1 = _uc.CalcHashValue(row1);
-                               int val2 = _uc.CalcHashValue(row2);
+                               int val1 = _uc.CalcHashValue(row1, _ignoreCase);
+                               int val2 = _uc.CalcHashValue(row2, _ignoreCase);
                                
-                               return val1 - val2;
+                               if (val1 > val2)
+                                       return 1;
+                               if (val1 == val2)
+                                       return 0;
+                               return -1;
                        }
                }
        }