merging the Mainsoft branch to the trunk
authorKonstantin Triger <kostat@mono-cvs.ximian.com>
Sun, 15 May 2005 23:15:37 +0000 (23:15 -0000)
committerKonstantin Triger <kostat@mono-cvs.ximian.com>
Sun, 15 May 2005 23:15:37 +0000 (23:15 -0000)
svn path=/trunk/mcs/; revision=44547

1  2  3 
mcs/class/System.Data/ChangeLog
mcs/class/System.Data/Mono.Data.SqlExpressions/ChangeLog
mcs/class/System.Data/System.Data.Common/ChangeLog
mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs
mcs/class/System.Data/System.Data.Common/DbDataReader.cs
mcs/class/System.Data/System.Data.Common/RecordCache.cs
mcs/class/System.Data/System.Data.dll.sources
mcs/class/System.Data/System.Data/ChangeLog
mcs/class/System.Data/System.Data/DataRow.cs
mcs/class/System.Data/System.Data/DataRowCollection.cs
mcs/class/System.Data/System.Data/DataTable.cs

index 591f498bc281006ae143d91e688cbf4d9b6eb201,668c0a67b2a45187773216e2cab469114c0e3975,668c0a67b2a45187773216e2cab469114c0e3975..f87f80143d22497ef786e58c7bcd217e2e4e5d19
 ++2005-05-04  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * System.Data.dll.sources: Added DataTableClearEventArgs.cs and
 ++     DataTableClearEventHandler.cs.
 ++
 ++2005-04-27  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * System.Data_test.dll.sources: Added DataTableReaderTest.cs
 ++
 ++2005-04-22  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * System.Data_test.dll.sources: Added DataTableLoadRowTest.cs.
 ++
+  2005-01-05  Konstantin Triger <kostat@mainsoft.com>
+  
+       * DbCommandOptionalFeatures.cs, DbConnectionString.cs, DbConnectionOptions.cs: revert to r43344
+  
+  2005-01-05  Konstantin Triger <kostat@mainsoft.com>
+       
+       * DbDataAdapter.cs: Rostore the Dispose logic
+  
+  2005-04-28  Konstantin Triger <kostat@mainsoft.com>  Sureshkumar T  <tsureshkumar@novell.com>
+  
+       * DataView.cs: Nullify an index when Closed
+  
+  2005-04-27  Konstantin Triger <kostat@mainsoft.com>
+  
+       * DataRow.cs: Removed unneeded check of RowState
+  
+  2005-04-27  Konstantin Triger <kostat@mainsoft.com>
+  
+       * ConstraintCollection: throw DuplicateException only if names match exactly with Table's locale
+  
   2005-04-08  Raja R Harinath  <rharinath@novell.com>
   
        * Makefile (EXTRA_DISTFILES): Add app_test_2.0.config.
index c2effbe8714b440a5bbda5b803ad7ab1db368883,53948f9974d31f805a96ca5fbd75c5c6f13d42a1,53948f9974d31f805a96ca5fbd75c5c6f13d42a1..25234b12b86657478237277786a9305afe2bbcc0
@@@@ -1,7 -1,6 -1,6 +1,11 @@@@
 --     * IExpression interface: Added DependsOn(DataColumn) method, which checks whether the Expression contains a specific column
+  2005-05-02 Konstantin Triger <kostat@mainsoft.com>
+  
+++        * IExpression interface: Added DependsOn(DataColumn) method, which checks whether the Expression contains a specific column
+++
 ++2005-04-26 Gonzalo Paniagua Javier <gonzalo@ximian.com>
 ++
 ++     * Tokenizer.cs: make it not rely in exceptions being thrown to know that
 ++     the array is entirely processed.
   
   2005-02-10  Atsushi Enomoto  <atsushi@ximian.com>
   
index b145a8ff96221b0dcaf083415bab82a4e575cf1a,f7468fa678287a3ae174326415a8a0c1b41de298,589f27428ba5f16adcc3d8ebdf2f2991a01e60d1..c89271f1bb289945b870ee0193292b260bb334da
++ 2005-05-16 Konstantin Triger <kostat@mainsoft.com>
++ 
++      * Index.cs: validation that the updated row belongs to the index
++ 
+  2005-05-02 Konstantin Triger <kostat@mainsoft.com>
+  
+       * DataContainer.cs: 
+               Added CharDataContainer, SByteDataContainer, UInt16DataContainer, UInt32DataContainer, UInt64DataContainer, DateTimeDataContainer, DecimalDataContainer
+               SetItemFromDataRecord: Changed to work with ISafeDataRecord or through GetValue to enable conversion
+               return DBNull.Value when the stored value is null
+       
+       * DbDataAdapter.cs:
+               Ensure correct order for LoadDataRow
+               Fixing schema creation
+               Use NewRowArray API
+       
+       * DbEnumerator.cs:
+               LoadSchema: Retrieve needed fields only
+       
+       * RecordCache.cs:
+               Added Rows-to-Records mapping
+               Added ReadIDataRecord method for correct handling of default/auto increment values
+       
+       * Added Index.cs: Index implementation
+       * Added Key.cs: Index descriptor implementation
+  
+  
 ++2005-04-27  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * DbDataReader.cs: Added static method to construct the schema
 ++     table with default schema. Could be reused in many places.
 ++
 ++2005-04-22  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * DbDataAdapter.cs: Moved FillTable and BuildSchema as static
 ++     methods as they are not operating on the current instance. This
 ++     could be reused to fill any table from a data reader.
 ++
 ++     * RecordCache.cs: While disposing records, make sure that the
 ++     record is not already disposed. i.e. to make sure later the same
 ++     record is not reused. Implemented a static method to compare two
 ++     version of records in a container.
 ++
   2005-04-18  Sureshkumar T  <tsureshkumar@novell.com>
   
        * DataAdapter.cs: Implemenetd OnFillError handler.
   
   2003-10-22  Eran Domb  <erand@miansoft.com>
   
---     * DbDataAdapter.cs (Fill): add only the mapped column to the dataTable (not all columns of dataReader).\r
---            Also closing the dataReader if an exception is thrown.\r
---     (Fill): the same as above.\r
---     (SetupSchema): in now return string (the table name). \r
---     (GetFillParameters): fix a bug.\r
---     (BuildSchema) \96 it now return Hashtable. Add columns to the table only if there is a mapping. Build an Hashtable that maps the columns from the table to the column from the reader.\r
+++     * DbDataAdapter.cs (Fill): add only the mapped column to the dataTable (not all columns of dataReader).
+++            Also closing the dataReader if an exception is thrown.
+++     (Fill): the same as above.
+++     (SetupSchema): in now return string (the table name). 
+++     (GetFillParameters): fix a bug.
+++     (BuildSchema) \96 it now return Hashtable. Add columns to the table only if there is a mapping. Build an Hashtable that maps the columns from the table to the column from the reader.
        (Update): first open the connection if needed. Catch an exception of the ExecuteQuery.
        
   
index 563aad68a0bcc92c2edb604b10e86d141dbe5936,56d4267492779b3028286783c6eae5a5514bfb00,56d4267492779b3028286783c6eae5a5514bfb00..a895a21cc8183bdc54710273329d2ae0a296aebb
@@@@ -332,100 -331,57 -331,57 +332,94 @@@@ namespace System.Data.Common 
                        return Fill (dataSet, srcTable, command.ExecuteReader (commandBehavior), startRecord, maxRecords);
                }
   
 --             private bool FillTable (DataTable dataTable, IDataReader dataReader, int startRecord, int maxRecords, ref int counter) 
 ++             private bool FillTable (DataTable dataTable, IDataReader dataReader, int startRecord, int maxRecords, ref int counter)
                {
 --                     if (dataReader.FieldCount == 0) {
 ++                     if (dataReader.FieldCount == 0)
                                return false;
 --                     }
   
 --                     
+                       int counterStart = counter;
+++
                        int[] mapping = BuildSchema (dataReader, dataTable, SchemaType.Mapped);
-                          try {
-                                  FillTable (dataTable, dataReader, startRecord, maxRecords, mapping,
-                                             AcceptChangesDuringFill, ref counter);
-                          } catch (Exception e) {
-                                  object[] readerArray = new object[dataReader.FieldCount];
-                                  object[] tableArray = new object[dataReader.FieldCount];
-                                  // we get the values from the datareader
-                                  dataReader.GetValues (readerArray);
-                                  // copy from datareader columns to table columns according to given mapping
-                                  int count = 0;
-                                  for (int i = 0; i < dataTable.Columns.Count; i++) {
-                                          if (mapping [i] >= 0)
-                                                  tableArray[count++] = readerArray[mapping[i]];
-                                  }
-                                  FillErrorEventArgs args = CreateFillErrorEvent (dataTable, tableArray, e);
-                                  OnFillError (args);
-                                  if(!args.Continue) {
-                                          return false;
-                                  }
-                          }
-                       return true;
-               }
   
-                  /// <summary>
-                  ///     Fills the given datatable using values from reader. if a column 
-                  ///     does not have a mapped reader column (-1 in mapping), that will 
-                  ///     be filled with default value. 
-                  /// </summary>
-               internal static void FillTable (DataTable dataTable, 
-                                                 IDataReader dataReader, 
-                                                 int startRecord, 
-                                                 int maxRecords, 
-                                                 int [] mapping,
-                                                 bool acceptChanges,
-                                                 ref int counter) 
-                  {
-                          if (dataReader.FieldCount == 0)
-                               return ;
+                       int[] sortedMapping = new int[mapping.Length];
+                       int length = sortedMapping.Length;
+                       for(int i=0; i < sortedMapping.Length; i++) {
+                               if (mapping[i] >= 0)
+                                       sortedMapping[mapping[i]] = i;
+                               else
+                                       sortedMapping[--length] = i;
+                       }
   
-                          for (int i = 0; i < startRecord; i++)
-                                  dataReader.Read ();
+                               for (int i = 0; i < startRecord; i++) {
+                                       dataReader.Read ();
+                               }
+  
+                       while (dataReader.Read () && (maxRecords == 0 || (counter - counterStart) < maxRecords)) {
+                               try {
+                                       dataTable.BeginLoadData ();
+                                       dataTable.LoadDataRow (dataReader, sortedMapping, length, AcceptChangesDuringFill);
+                                       dataTable.EndLoadData ();
+                                       counter++;
+                               } 
+                               catch (Exception e) {
+                                       object[] readerArray = new object[dataReader.FieldCount];
+                                       object[] tableArray = new object[mapping.Length];
+                                       // we get the values from the datareader
+                                       dataReader.GetValues (readerArray);
+                                       // copy from datareader columns to table columns according to given mapping
+                                       for (int i = 0; i < mapping.Length; i++) {
+                                               if (mapping[i] >= 0) {
+                                                       tableArray[i] = readerArray[mapping[i]];
+                                               }
+                                       }
+                                       FillErrorEventArgs args = CreateFillErrorEvent (dataTable, tableArray, e);
+                                       OnFillError (args);
+                                       if(!args.Continue) {
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               }
   
-                          int counterStart = counter;
-                          while (dataReader.Read () && (maxRecords == 0 || (counter - counterStart) < maxRecords)) {
-                                  dataTable.BeginLoadData ();
-                                  dataTable.LoadDataRow (dataReader, mapping, acceptChanges);
-                                  dataTable.EndLoadData ();
-                                  counter++;
-                          }
-                  }
 ++#if NET_2_0
 ++                /// <summary>
 ++                ///     Fills the given datatable using values from reader. if a value 
 ++                ///     for a column is  null, that will be filled with default value. 
 ++                /// </summary>
 ++                /// <returns>No. of rows affected </returns>
 ++             internal static int FillFromReader (DataTable table,
 ++                                                    IDataReader reader,
 ++                                                    int start, 
 ++                                                    int length,
 ++                                                    int [] mapping,
 ++                                                    LoadOption loadOption
 ++                                                    )
 ++                {
 ++                        if (reader.FieldCount == 0)
 ++                             return 0 ;
 ++
 ++                        for (int i = 0; i < start; i++)
 ++                                reader.Read ();
 ++
 ++                        int counter = 0;
 ++                        object [] values = new object [mapping.Length];
 ++                        while (reader.Read () &&
 ++                               (length == 0 || counter < length)) {
 ++                                
 ++                                for (int i = 0 ; i < mapping.Length; i++)
 ++                                        values [i] = mapping [i] < 0 ? null : reader [mapping [i]];
 ++                                        
 ++                                table.BeginLoadData ();
 ++                                table.LoadDataRow (values, loadOption);
 ++                                table.EndLoadData ();
 ++                                counter++;
 ++                        }
 ++                        return counter;
 ++                }
 ++
 ++#endif // NET_2_0
 ++
                public override DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType) 
                {
                        return FillSchema (dataSet, schemaType, SelectCommand, DefaultSourceTableName, CommandBehavior.Default);
                [MonoTODO ("Test")]
                private int[] BuildSchema (IDataReader reader, DataTable table, SchemaType schemaType)
                {
-                          return BuildSchema (reader, table, schemaType, MissingSchemaAction,
-                                              MissingMappingAction, TableMappings);
-               }
+++                         return BuildSchema (reader, table, schemaType, MissingSchemaAction,
+++                                             MissingMappingAction, TableMappings);
+++                }
 ++
 ++                /// <summary>
 ++                ///     Creates or Modifies the schema of the given DataTable based on the schema of
 ++                ///     the reader and the arguments passed.
 ++                /// </summary>
-                  internal static int[] BuildSchema (IDataReader reader, 
-                                                     DataTable table, 
+++                internal static int[] BuildSchema (IDataReader reader,
+++                                                   DataTable table,
 ++                                                   SchemaType schemaType,
 ++                                                   MissingSchemaAction missingSchAction,
 ++                                                   MissingMappingAction missingMapAction,
 ++                                                   DataTableMappingCollection dtMapping
 ++                                                   )
-               {
+++               {
                        int readerIndex = 0;
-                       int[] mapping = new int[reader.FieldCount + table.Columns.Count]; // mapping the reader indexes to the datatable indexes
-                          for (int i =0 ; i < mapping.Length; i++) 
-                                  mapping [i] = -1; // no mapping
-  
+                       // FIXME : this fails if query has fewer columns than a table
+                       int[] mapping = new int[table.Columns.Count]; // mapping the reader indexes to the datatable indexes
+                       
+                       for(int i=0; i < mapping.Length; i++) {
+                               mapping[i] = -1;
+                       }
+                       
                        ArrayList primaryKey = new ArrayList ();
                        ArrayList sourceColumns = new ArrayList ();
+                       bool createPrimaryKey = true;
   
                        foreach (DataRow schemaRow in reader.GetSchemaTable ().Rows) {
                                // generate a unique column name in the source table.
                                        
                                        table.TableName = tableMapping.DataSetTable;
                                        // check to see if the column mapping exists
 --                                     DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction(tableMapping.ColumnMappings, realSourceColumnName, MissingMappingAction);
 ++                                     DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction(tableMapping.ColumnMappings, realSourceColumnName, missingMapAction);
                                        if (columnMapping != null)
                                        {
+                                               Type columnType = (Type)schemaRow["DataType"];
                                                DataColumn col =
                                                        columnMapping.GetDataColumnBySchemaAction(
                                                        table ,
-                                                       (Type)schemaRow["DataType"],
+                                                       columnType,
 --                                                     MissingSchemaAction);
 ++                                                     missingSchAction);
   
                                                if (col != null)
                                                {
                                                        // if the column is not in the table - add it.
                                                        if (table.Columns.IndexOf(col) == -1)
                                                        {
 --                                                             if (MissingSchemaAction == MissingSchemaAction.Add 
 --                                                                    || MissingSchemaAction == MissingSchemaAction.AddWithKey)
 ++                                                             if (missingSchAction == MissingSchemaAction.Add 
-                                                                      || missingSchAction == MissingSchemaAction.AddWithKey)
+++                                                                     || missingSchAction == MissingSchemaAction.AddWithKey)
                                                                        table.Columns.Add(col);
 --                                                        if (MissingSchemaAction == MissingSchemaAction.AddWithKey) {
+  
+                                                               int[] tmp = new int[mapping.Length + 1];
+                                                               Array.Copy(mapping,0,tmp,0,col.Ordinal);
+                                                               Array.Copy(mapping,col.Ordinal,tmp,col.Ordinal + 1,mapping.Length - col.Ordinal);
+                                                               mapping = tmp;
+                                                       }                               
+                                                       bool isAutoIncrement = (bool)schemaRow["IsAutoIncrement"];
+                                                       bool allowDBNull = (bool)schemaRow["AllowDBNull"];
+                                                       bool isReadOnly =(bool)schemaRow["IsReadOnly"];
+                                                       bool isKey = (bool)schemaRow["IsKey"];                                                  
+                                                       bool isUnique = (bool)schemaRow["IsUnique"];
+  
+++                            if (missingSchAction == MissingSchemaAction.AddWithKey) {
+                                                               // fill woth key info                                                           
+                                                               if (isAutoIncrement && DataColumn.CanAutoIncrement(columnType)) {
+                                                                       col.AutoIncrement = true;
+                                                                       if (!allowDBNull)
+                                                                               col.AllowDBNull = false;
+                                                               }
+  
+                                                               if (columnType == DbTypes.TypeOfString) {
+                                                                       col.MaxLength = (int)schemaRow["ColumnSize"];
+                                                               }
+  
+                                                               if (isReadOnly)
+                                                                       col.ReadOnly = true;
+                                                       }
+                                                                                                                                                                       
+                                                       if (!allowDBNull && (!isReadOnly || isKey))
+                                                               col.AllowDBNull = false;
+                                                       if (isUnique && !isKey && !columnType.IsArray) {
+                                                               col.Unique = true;
+                                                               if (!allowDBNull)
+                                                                       col.AllowDBNull = false;
                                                        }
   
-                                                          if (missingSchAction == MissingSchemaAction.AddWithKey) {
-                                                                  if (!schemaRow["IsKey"].Equals (DBNull.Value))
-                                                                          if ((bool) (schemaRow ["IsKey"]))
-                                                                                  primaryKey.Add (col);
-                                                                  
-                                                                  col.AutoIncrement = (bool) schemaRow ["IsAutoIncrement"];
-                                                          }
+                                                       if (isKey) {
 --                                                                                primaryKey.Add (col);
+++                                primaryKey.Add (col);
+                                                               if (allowDBNull)
+                                                                       createPrimaryKey = false;
 --                                                        }
+++                            }
                                                        
                                                        // add the ordinal of the column as a key and the index of the column in the datareader as a value.
-                                                       mapping[col.Ordinal] = readerIndex;
+                                                       mapping[col.Ordinal] = readerIndex++;
+                                               }
+                                       }
+                               }
+                       }
+                       if (primaryKey.Count > 0) {
+                               DataColumn[] colKey = (DataColumn[])(primaryKey.ToArray(typeof (DataColumn)));
+                               if (createPrimaryKey)
+                                       table.PrimaryKey = colKey;
+                               else {
+                                       UniqueConstraint uConstraint = new UniqueConstraint(colKey);
+                                       for (int i = 0; i < table.Constraints.Count; i++) {
+                                               if (table.Constraints[i].Equals(uConstraint)) {
+                                                       uConstraint = null;
+                                                       break;
                                                }
                                        }
+  
+                                       if (uConstraint != null)
+                                               table.Constraints.Add(uConstraint);
                                }
-                               readerIndex++;
                        }
-                       if (primaryKey.Count > 0)
-                               table.PrimaryKey = (DataColumn[])(primaryKey.ToArray(typeof (DataColumn)));
   
                        return mapping;
 --             }
 ++                        
 ++                }
   
                [MonoTODO]
                object ICloneable.Clone ()
index 92bf0d239bcabe2c93acf1d5b4a08cb5b236fc24,0e7de52eb2c945b16b8ddb31c2e904c9735c5d95,0e7de52eb2c945b16b8ddb31c2e904c9735c5d95..7338240e1e03f66c6e417d4b7d85bbecf497ea2b
@@@@ -98,30 -116,49 -116,49 +116,49 @@@@ namespace System.Data.Commo
                                recordIndex = NewRecord();
                        }
   
-                       foreach(DataColumn fromColumn in fromTable.Columns) {
-                               DataColumn column = _table.Columns[fromColumn.ColumnName];
-                               if (column != null) {
-                                       column.DataContainer.CopyValue(fromColumn.DataContainer,fromRecordIndex,recordIndex);
+                       try
+                       {
 --                             foreach(DataColumn fromColumn in fromTable.Columns) \r
+++                             foreach(DataColumn fromColumn in fromTable.Columns) 
+                               {
+                                       DataColumn column = _table.Columns[fromColumn.ColumnName];
 --                                     if (column != null) \r
+++                                     if (column != null) 
+                                       {
+                                               column.DataContainer.CopyValue(fromColumn.DataContainer,fromRecordIndex,recordIndex);
+                                       }
                                }
+  
+                               return recordIndex;
                        }
+                       catch
+                       {
+                               if (toRecordIndex == -1)
+                                       DisposeRecord(recordIndex);
   
-                       return recordIndex;
+                               throw;
+                       }
                }
   
-                  /// <summary>
-                  ///     Compares two records in the given data table. The numbers are the offset
-                  ///     into the container tables.
-                  /// </summary>
-                  internal static bool CompareRecords (DataTable table, int x, int y)
-                  {
-                          foreach (DataColumn dc in table.Columns) {
-                                  if (dc.DataContainer.CompareValues (x, y) != 0)
-                                          return false;
-                          }
-                          return true;
-                  }
-                  
-               #endregion // Methods
+               internal void ReadIDataRecord(int recordIndex, IDataRecord record, int[] mapping, int length)
+               {
+                       if ( mapping.Length > _table.Columns.Count)
+                               throw new ArgumentException ();
+  
+                       int i=0;
+                       for(; i < length; i++) {
+                               DataColumn column = _table.Columns[mapping[i]];
+                               column.DataContainer.SetItemFromDataRecord(recordIndex, record,i);
+                       }
   
 --                             if ( column.AutoIncrement ) \r
+                       for (; i < mapping.Length; i++)
+                       {
+                               DataColumn column = _table.Columns[mapping[i]];
+++                             if ( column.AutoIncrement ) 
+                                       column.DataContainer[recordIndex] = column.AutoIncrementValue ();
+                               else
+                                       column.DataContainer[recordIndex] = column.DefaultValue;
+                       }
+               }
+  
+               #endregion // Methods
        }
   }
index f1de05208c28cfe93c3901da5192c2ab732fdd61,09354552b8b9f71fc95e00f377105c2fd868ff47,d91d2719ff82287d64e3e8b8195958116219dc2f..10178e5bd2c7ec02b9b51505b213a3e087998128
 ++2005-05-11  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     fix for "import row does not import deleted records"
 ++
 ++     * UniqueConstraint.cs: Make a way to access value even from a
 ++     deleted record. deleted records are added to the collection by
 ++     ImportRow method.
 ++
 ++     * DataRow.cs:
 ++     - Added restriction-less methods GetValue to fetch a
 ++     value even if it is in deleted state.
 ++     - If a row is detached, don't try to delete it from indexes.
 ++     - sanity check for record_index in CopyValuesToRow method
 ++
 ++2005-05-05  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * DataTableReader.cs: Implemented Delete handler and move the
 ++     current pointer accordingly.
 ++
 ++2005-05-04  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * DataTableReader.cs: Added event handlers to make reader stable
 ++     when the datasource is modified. Thanks to Umadevi for giving the
 ++     review comments for this implementation.
 ++
 ++     * DataTable.cs: Clear (): Raise TableCleared event.
 ++
 ++     * DataTableClearEventArgs.cs: Args for DataTableClearEventHandler.
 ++
 ++     * DataTableClearEventHandler.cs: Handler for DataTable.TableClear
 ++     event.
 ++
 ++     * DataRow.cs: AcceptChanges: raise row changing & row changed
 ++     events.
 ++
 ++     * DataRowCollection.cs: Clear : remove rows from indexes
 ++
 ++2005-05-02  Atsushi Enomoto  <atsushi@ximian.com>
 ++
 ++     * XmlSchemaDataImporter.cs : XmlSchemaParicle might be XmlSchemaAny.
 ++       This fixes bug #74784.
 ++
 ++2005-04-29  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * DataTableReader.cs: removed use of _first. throw if given index
 ++     is out of range of columns. Copy DataTable [] to local array so
 ++     that not to be disturbed.
 ++
 ++2005-04-27  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * DataTableReader.cs: Implemented most of the TODO.
 ++
 ++2005-04-22  Sureshkumar T  <tsureshkumar@novell.com>
 ++
 ++     * LoadOption.cs: Changed the enums. Keeping old values for
 ++     migration.
 ++
 ++     * DataTable.cs: Implemented methods Load and its overloads. Also
 ++     implemented LoadDataRow.
 ++
 ++     * DataRowCollection.cs: Added a variation of the Find method to
 ++     return a row even if it is of state Deleted. This is required for
 ++     DataTable.LoadDataRow method.
 ++
 ++     * DataRow.cs: Implemented internal helper method Load for loading
 ++     values from an object array and given an LoadOption (2.0 feature).
 ++
 ++     * DataRowAction.cs: Added few more enums for .net 2.0. Sorted
 ++     alphabetically.
 ++
++ 2005-05-16 Konstantin Triger <kostat@mainsoft.com>
++ 
++      * UniqueConstraint.cs : IsNull check is relevant for rows having default row version.
++      * DataTable.cs : The row should be validated when imported
++      * DataRowCollection.cs : if the row does not contain Proposed neither Current version, it's irrelevant for validation
++ 
+  2005-04-26 Boris Kirzner <borisk@mainsoft.com>
+  
+       * UniqueConstraint.cs :
+               - Add indication whenever the constraint belongs to collection. 
+               - Calculation of IsPrimaryKey simplified.
+               - If constraint is based on single column, the column becomes unique.
+               - Use boolean IsConstraintViolated() instead of AssertConstraint().
+               - Use Index.Duplicates to proper exception message formatting.
+               - AssertConstraint(DataRow) changed to suite new indexes interface.
+               - Added CanRemoveFromCollection method.
+               - Contains() method renamed to IsColumnContained().
+       * RelatedDataView.cs : added new class.
+       * MergeManager.cs :
+               - Reset indexes after merge.
+               - Add new tables when row array is merged into dataset.
+               - Clean proposed record in MergeRow.
+               - Inherit nesting on creating new relations in target data set.
+               - Avoid double loop on constraints collection.
+       * Locale.cs : added new class.
+       * ISafeDataRecord.cs : added new interface.
+       * Index.cs : commented out. Index implementation moved to System.Data.Common.
+       * ForeignKeyConstraint.cs : 
+               - No more use of childColumnsExtended since new indexes allow duplicate records.
+               - Constraints can not be created on expression columns.
+               - Removed unnecessary delegation.
+               - Use boolean IsConstraintViolated() instead of AssertConstraint(). 
+               - Use proper exception message formatting.
+               - Contains() method renamed to IsColumnContained().
+       * DataViewRowState.cs : use enum members to simplify notation.
+       * MergeManager.cs : implemented RelationCollectionChanged().
+       * DataView.cs :  new implementation.
+       * DataTableCollection.cs : 
+               - Added boundary check in indexer.
+               - More accurate handling in AddRange().
+               - Raise event in Remove().
+       * DataTable.cs :
+               - Hold primary key as constraint.
+               - Added accurate handling of DefaultView.
+               - Hold DataRowBuilder per table.
+               - Proper exception messages if enforce Constraints is violated.
+               - If there is no rows, Compute() returns DBNull.
+               - Use DataRow properties instead of private members.
+               - CopyProperties() fixed.
+               - Raise proper events in EndInit().
+               - Proper order of violation checks in EndLoadData().
+               - Create array of rows using NewRowArray().
+               - ImportRow handles rows according to their versions.
+               - LoadDataRow make use of records (instead of raw object array).
+               - Added and implemented LoadDataRow() that gets IDataRecord as a parameter (used in Fill)
+               - Select() uses indexes filtering and sorting ability (instead of "loop-throw-sort" approach).
+               - Removed redundant RowSorter and Sortable column classes.
+               - ParseSortString() fixed to threat bracketed column names.
+               - Table holds collection of property descriptors.
+       * DataSet.cs :
+               - Reset table case sensitive indexes on CaseSensitive change.
+               - EnforceConstraints update logic moved to internal method (used by DataTable).
+               - InAddChangedRow first add row and than copy values for proper handling of default values.
+       * DataRowView.cs :
+               - Changed private member names to suite name convention.
+               - CancelEdit() fixed.
+               - CreateChildView() delegates to DataView.
+               - IsNew fixed.
+               - Proper exception messages in indexers.
+               - RowVersion uses DataView.
+               - GetProperties() delegates to corresponding table if needed.
+       * DataRowCollection.cs :
+               - Common Add() logic moved to AddInternal() (used also by DataTable).
+               - Removed redundant check from Contains().
+               - Dalegate Find() calls when possible.
+               - Remove() fixed.
+               - RomoveAt() delegates to Remove().
+               - Optimized constraints check in row validation.
+       * DataRelationPropertyDescriptor.cs : added new class.
+       * DataRelationCollection.cs :
+               - Indexers fixed.
+               - Fixed order of actions in AddCore().
+               - RemoveCore() also delegates to base.
+               - Add relation to dataset also in AddCore().
+               - Remove relation from dataset also in RemoveCore().
+               - InTransition hold a data relation so we can properly identify the "in transition" state.
+               - Added threat of parent and child table s property descriptors in Add().
+               - Common Add() logic moved to AddCore().
+               - Clear() fixed.
+               - Remove() threats "in transition" state properly.
+               - Remove methods delegate to single implementation.
+       * DataColumnPropertyDescriptior.cs :
+               - Added new constructor.
+               - Commented out redundant method.
+       * DataColumnCollection.cs :
+               - Boundary check in indexer.
+               - RegisterName and UnregisterName become internal (used also by DataColumn).
+               - Fixed AddRange().
+               - Fixed CanRemove().
+               - Rethrow correct exception in Clear();
+               - Change in collection resets parent table property descriptors.
+               - Added PostEndEdit() helper method (used by DataTable).
+       * DataColumn.cs :
+               - Private member names changed to suite name convention.
+               - Created method for CanAutoIncrement() logic.
+               - Proper handling of column name update.
+               - Proper exception messages on expression update.
+               - Proper namespace handling (delegates to table when needed).
+               - Removed redundant check in Unique update.
+               - Implemented internal Clone().
+               - GetParentRalation() and GetChildRelation() become private.
+       * Constraint.cs :
+               - Added abstract methods (implemented in UniqueConstraint and ForeignKeyConstraint).
+               - Simplified index update.
+       * ConstraintCollection.cs :
+               - Use Locale instead of CaseSensitive in column names comparison.
+               - Removed #ifdef
+               - Rethrow correct exception type in Add().
+               - Proper update of table primary key in Add().
+               - Delegate CanRemove() to constraint.
+               - Remove table primary key in Clear();
+               - Delegate "can remove" check to constraint in Remove().
+               - Removed unnecessary methods and properties.
+       * DataRow.cs :
+               - RowSate becomes calculated property.
+               - Use properties instead of private members where possible.
+               - Fixed indexer.
+               - Fixed order of actions in ItemArray update.
+               - Fixed DetachRow().
+               - Added ImportRecord() method.
+               - Removed redundant SetValuesFromDataRecord().
+               - Fixed IndexFromVersion().
+               - Added VersionFromIndex() method. Returns row version the passed record index corresponds to.
+               - Fixed AcceptChanges().
+               - Fixed creating proposed version in BeginEdit();
+               - Added record disposal in Delete().
+               - Fixed CheckChildRows().
+               - EndEdit() fixed. Checks for readonly. Uses straight flow instead of "try and fix if fail" approach.
+               - GetChildRows() and GetPrarentRows() rewrited. Use records and indexes for rows lookup.
+               - GetColumnError() delegates to another implementation.
+               - HasVersion() fixed.
+               - RejectCahnges checks on child rows before passing through.
+               - SetParentRow() fixed. Create relation collection if needed. Use typed data container value copy.
+               - CopyErrors() logic moved to separate method (used also by DataTable).
+       * ExpressionElement.cs : added new class.
+       * Res.cs : added new class.
+  
   2005-04-20  Jordi Mas i Hernandez <jordi@ximian.com>
   
        * DataViewManager.cs: implements TypedList.GetListName used in SWF
index a899d7fa9b24eec491626a91bf779ce5f4a760ad,7ec86fcc0264d94d9c70f89853c77b821e4c8bee,4c34ef639606e9c875a14b5011013028f95c819e..66154c183e85978e00bdd193d117bed8bebbbc34
 - //\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
 - //\r
 - // Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
 - //\r
 - // Permission is hereby granted, free of charge, to any person obtaining\r
 - // a copy of this software and associated documentation files (the\r
 - // "Software"), to deal in the Software without restriction, including\r
 - // without limitation the rights to use, copy, modify, merge, publish,\r
 - // distribute, sublicense, and/or sell copies of the Software, and to\r
 - // permit persons to whom the Software is furnished to do so, subject to\r
 - // the following conditions:\r
 - // \r
 - // The above copyright notice and this permission notice shall be\r
 - // included in all copies or substantial portions of the Software.\r
 - // \r
 - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
 - // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
 - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
 - // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
 - // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
 - // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
 - // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
 - //\r
 - \r
 - using System;\r
 - using System.Collections;\r
 - using System.Globalization;\r
 - using System.Xml;\r
 - \r
 - using System.Data.Common;\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
 -              internal int _original = -1;\r
 -              internal int _current = -1;\r
 -              internal int _proposed = -1;\r
 - \r
 -              private ArrayList _columnErrors;\r
 -              private string rowError;\r
 -              internal int xmlRowID = 0;\r
 -              internal bool _nullConstraintViolation;\r
 -              private string _nullConstraintMessage;\r
 -              private bool _hasParentCollection;\r
 -              private bool _inChangingEvent;\r
 -              private int _rowId;\r
 - \r
 -              private XmlDataDocument.XmlDataElement mappedElement;\r
 -              internal bool _inExpressionEvaluation = false;\r
 - \r
 -              #endregion // Fields\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
 -                      // Get the row id from the builder.\r
 -                      _rowId = builder._rowId;\r
 - \r
 -                      rowError = String.Empty;\r
 - \r
 -                      // create mapped XmlDataElement\r
 -                      DataSet ds = _table.DataSet;\r
 -                      if (ds != null && ds._xmlDataDocument != null)\r
 -                              mappedElement = new XmlDataDocument.XmlDataElement (this, _table.Prefix, _table.TableName, _table.Namespace, ds._xmlDataDocument);\r
 -              }\r
 - \r
 -              internal DataRow(DataTable table,int rowId)\r
 -              {\r
 -                      _table = table;\r
 -                      _rowId = rowId;\r
 -              }\r
 - \r
 -              #endregion // Constructors\r
 - \r
 -              #region Properties\r
 - \r
 -              private ArrayList ColumnErrors\r
 -              {\r
 -                      get {\r
 -                              if (_columnErrors == null) {\r
 -                                      _columnErrors = new ArrayList();\r
 -                              }\r
 -                              return _columnErrors;\r
 -                      }\r
 - \r
 -                      set {\r
 -                              _columnErrors = value;\r
 -                      }\r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Gets a value indicating whether there are errors in a row.\r
 -              /// </summary>\r
 -              public bool HasErrors {\r
 -                      get {\r
 -                              if (RowError != string.Empty)\r
 -                                      return true;\r
 - \r
 -                              foreach(String columnError in ColumnErrors) {\r
 -                                      if (columnError != null && columnError != 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
 - \r
 -                              DataColumn column = _table.Columns[columnIndex];\r
 -                              _table.ChangingDataColumn (this, column, value);\r
 -                              \r
 -                              if (value == null && column.DataType != typeof(string)) {\r
 -                                      throw new ArgumentException("Cannot set column " + column.ColumnName + " to be null, Please use DBNull instead");\r
 -                              }\r
 -                              \r
 -                              CheckValue (value, column);\r
 - \r
 -                              bool orginalEditing = Proposed >= 0;\r
 -                              if (!orginalEditing) {\r
 -                                      BeginEdit ();\r
 -                              }\r
 -                              \r
 -                              column[Proposed] = value;\r
 -                              _table.ChangedDataColumn (this, column, value);\r
 -                              if (!orginalEditing) {\r
 -                                      EndEdit ();\r
 -                              }\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
 -                              if (column.Table != Table)\r
 -                                      throw new ArgumentException ("The column does not belong to this table.");\r
 -                              int columnIndex = column.Ordinal;\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
 -                              // Accessing deleted rows\r
 -                              if (!_inExpressionEvaluation && RowState == DataRowState.Deleted && version != DataRowVersion.Original)\r
 -                                      throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");\r
 -                              \r
 -                              DataColumn column = _table.Columns[columnIndex];\r
 -                              int recordIndex = IndexFromVersion(version);\r
 - \r
 -                              if (column.Expression != String.Empty) {\r
 -                                      object o = column.CompiledExpression.Eval (this);\r
 -                                      if (o != null && o != DBNull.Value) {\r
 -                                              o = Convert.ChangeType (o, column.DataType);\r
 -                                      }\r
 -                                      column[recordIndex] = o;\r
 -                                      return column[recordIndex];\r
 -                              }\r
 - \r
 -                              if (RowState == DataRowState.Detached && version == DataRowVersion.Default && Proposed < 0)\r
 -                                      throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");\r
 -                              \r
 -                              return column[recordIndex];\r
 -                      }\r
 -              }\r
 -              \r
 -              /// <summary>\r
 -              /// Gets or sets all of the values for this row through an array.\r
 -              /// </summary>\r
 -              public object[] ItemArray {\r
 -                      get { \r
 -                              // row not in table\r
 -                              if (RowState == DataRowState.Detached)\r
 -                                      throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");\r
 -                              // Accessing deleted rows\r
 -                              if (RowState == DataRowState.Deleted)\r
 -                                      throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");\r
 -                              \r
 -                              object[] items = new object[_table.Columns.Count];\r
 -                              foreach(DataColumn column in _table.Columns) {\r
 -                                      items[column.Ordinal] = column[Current];\r
 -                              }\r
 -                              return items;\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
 -                              BeginEdit ();\r
 - \r
 -                              DataColumnChangeEventArgs e = new DataColumnChangeEventArgs();\r
 -                              foreach(DataColumn column in _table.Columns) {\r
 -                                      int i = column.Ordinal;\r
 -                                      object newVal = (i < value.Length) ? value[i] : null;\r
 - \r
 -                                      if (newVal == null)\r
 -                                              continue;\r
 -                                      \r
 -                                      e.Initialize(this, column, newVal);\r
 -                                      CheckValue (e.ProposedValue, column);\r
 -                                      _table.RaiseOnColumnChanging(e);\r
 -                                      column[Proposed] = e.ProposedValue;\r
 -                                      _table.RaiseOnColumnChanged(e);\r
 -                              }\r
 -                              \r
 -                              EndEdit ();\r
 -                      }\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 { \r
 -                              //return rowState; \r
 -                                if ((Original == -1) && (Current == -1))\r
 -                                      {\r
 -                                              return DataRowState.Detached;\r
 -                                      }\r
 -                                      if (Original == Current)\r
 -                                      {\r
 -                                              return DataRowState.Unchanged;\r
 -                                      }\r
 -                                      if (Original == -1)\r
 -                                      {\r
 -                                              return DataRowState.Added;\r
 -                                      }\r
 -                                      if (Current == -1)\r
 -                                      {\r
 -                                              return DataRowState.Deleted;\r
 -                                      }\r
 -                                      return DataRowState.Modified;\r
 -                      }\r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Gets the DataTable for which this row has a schema.\r
 -              /// </summary>\r
 -              public DataTable Table {\r
 -                      get { \r
 -                              return _table; \r
 -                      }\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 { \r
 -                              return xmlRowID; \r
 -                      }\r
 -                      set { \r
 -                              xmlRowID = value; \r
 -                      }\r
 -              }\r
 -              \r
 -              /// <summary>\r
 -              /// Gets and sets index of row.\r
 -              // </summary>\r
 -              internal int RowID {\r
 -                      get { \r
 -                              return _rowId; \r
 -                      }\r
 -                      set { \r
 -                              _rowId = value; \r
 -                      }\r
 -              }\r
 - \r
 -              internal int Original\r
 -              {\r
 -                      get {\r
 -                              return _original;\r
 -                      }\r
 -                      set {\r
 -                              if (Table != null) {\r
 -                                      //Table.RecordCache[_original] = null;\r
 -                                      Table.RecordCache[value] = this;\r
 -                              }\r
 -                              _original = value;\r
 -                      }\r
 -              }\r
 - \r
 -              internal int Current\r
 -              {\r
 -                      get {\r
 -                              return _current;\r
 -                      }\r
 -                      set {\r
 -                              if (Table != null) {\r
 -                                      //Table.RecordCache[_current] = null;\r
 -                                      Table.RecordCache[value] = this;\r
 -                              }\r
 -                              _current = value;\r
 -                      }\r
 -              }\r
 - \r
 -              internal int Proposed\r
 -              {\r
 -                      get {\r
 -                              return _proposed;\r
 -                      }\r
 -                      set {\r
 -                              if (Table != null) {\r
 -                                      //Table.RecordCache[_proposed] = null;\r
 -                                      Table.RecordCache[value] = this;\r
 -                              }\r
 -                              _proposed = value;\r
 -                      }\r
 -              }\r
 - \r
 -              #endregion\r
 - \r
 -              #region Methods\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
 -                      if (Proposed != -1) {\r
 -                              if (Current >= 0) {\r
 -                                      Table.RecordCache.DisposeRecord(Current);\r
 -                              }\r
 -                              Current = Proposed;\r
 -                              Proposed = -1;\r
 -                      }\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
 -                      if (Proposed >= 0) {\r
 -                              _table.RecordCache.DisposeRecord(Proposed);\r
 -                              if (Proposed == Current) {\r
 -                                      Current = -1;\r
 -                              }\r
 -                              if (Proposed == Original) {\r
 -                                      Original = -1;\r
 -                              }\r
 -                              Proposed = -1;\r
 -                      }\r
 - \r
 -                      if (Current >= 0) {\r
 -                              _table.RecordCache.DisposeRecord(Current);\r
 -                              if (Current == Original) {\r
 -                                      Original = -1;\r
 -                              }\r
 -                              Current = -1;\r
 -                      }\r
 - \r
 -                      if (Original >= 0) {\r
 -                              _table.RecordCache.DisposeRecord(Original);\r
 -                              Original = -1;\r
 -                      }\r
 - \r
 -                      _rowId = -1;\r
 -                      _hasParentCollection = false;\r
 -              }\r
 - \r
 -              internal void ImportRecord(int record)\r
 -              {\r
 -                      if (HasVersion(DataRowVersion.Proposed)) {\r
 -                              Table.RecordCache.DisposeRecord(Proposed);\r
 -                      }\r
 - \r
 -                      Proposed = record;\r
 - \r
 -                      foreach(DataColumn column in Table.Columns.AutoIncrmentColumns) {\r
 -                              column.UpdateAutoIncrementValue(column.DataContainer.GetInt64(Proposed));\r
 -                      }\r
 - \r
 -              }\r
 - \r
 -              private void CheckValue (object v, DataColumn col) \r
 -              {               \r
 -                      if (_hasParentCollection && col.ReadOnly) {\r
 -                              throw new ReadOnlyException ();\r
 -                      }\r
 - \r
 -                      if (v == null || v == DBNull.Value) {\r
 -                              if (col.AllowDBNull || col.AutoIncrement || col.DefaultValue != DBNull.Value) {\r
 -                                      return;\r
 -                              }\r
 - \r
 -                              //Constraint violations during data load is raise in DataTable EndLoad\r
 -                              this._nullConstraintViolation = true;\r
 -                              if (this.Table._duringDataLoad) {\r
 -                                      this.Table._nullConstraintViolationDuringDataLoad = true;\r
 -                              }\r
 -                              _nullConstraintMessage = "Column '" + col.ColumnName + "' does not allow nulls.";\r
 -                      \r
 -                      }\r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Gets or sets the custom error description for a row.\r
 -              /// </summary>\r
 -              public string RowError {\r
 -                      get { \r
 -                              return rowError; \r
 -                      }\r
 -                      set { \r
 -                              rowError = value; \r
 -                      }\r
 -              }\r
 - \r
 -              internal int IndexFromVersion(DataRowVersion version)\r
 -              {\r
 -                      switch (version) {\r
 -                              case DataRowVersion.Default:\r
 -                                      if (Proposed >= 0)\r
 -                                              return Proposed;\r
 - \r
 -                                      if (Current >= 0)\r
 -                                              return Current;\r
 - \r
 -                                      if (Original < 0)\r
 -                                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");\r
 - \r
 -                                      throw new DeletedRowInaccessibleException("Deleted row information cannot be accessed through the row.");\r
 - \r
 -                              case DataRowVersion.Proposed:\r
 -                                      return AssertValidVersionIndex(version, Proposed);\r
 -                              case DataRowVersion.Current:\r
 -                                      return AssertValidVersionIndex(version, Current);\r
 -                              case DataRowVersion.Original:\r
 -                                      return AssertValidVersionIndex(version, Original);\r
 -                              default:\r
 -                                      throw new DataException ("Version must be Original, Current, or Proposed.");\r
 -                      }\r
 -              }\r
 - \r
 -              private int AssertValidVersionIndex(DataRowVersion version, int index) {\r
 -                      if (index >= 0)\r
 -                              return index;\r
 - \r
 -                      throw new VersionNotFoundException(String.Format("There is no {0} data to accces.", version));\r
 -              }\r
 - \r
 -              internal DataRowVersion VersionFromIndex(int index) {\r
 -                      if (index < 0)\r
 -                              throw new ArgumentException("Index must not be negative.");\r
 - \r
 -                      // the order of ifs matters\r
 -                      if (index == Current)\r
 -                              return DataRowVersion.Current;\r
 -                      if (index == Original)\r
 -                              return DataRowVersion.Original;\r
 -                      if (index == Proposed)\r
 -                              return DataRowVersion.Proposed;\r
 - \r
 -                      throw new ArgumentException(String.Format("The index {0} does not belong to this row.", index)  );\r
 -              }\r
 - \r
 -              internal XmlDataDocument.XmlDataElement DataElement {\r
 -                      get { return mappedElement; }\r
 -                      set { mappedElement = value; }\r
 -              }\r
 - \r
 -              internal void SetOriginalValue (string columnName, object val)\r
 -              {\r
 -                      DataColumn column = _table.Columns[columnName];\r
 -                      _table.ChangingDataColumn (this, column, val);\r
 -                              \r
 -                      if (Original < 0 || Original == Current) { \r
 -                              Original = Table.RecordCache.NewRecord();\r
 -                      }\r
 -                      CheckValue (val, column);\r
 -                      column[Original] = val;\r
 -              }\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
 -                      CheckChildRows(DataRowAction.Commit);\r
 -                      switch (RowState) {\r
 -                              case DataRowState.Unchanged:\r
 -                                      return;\r
 -                      case DataRowState.Added:\r
 -                      case DataRowState.Modified:\r
 -                                      if (Original >= 0) {\r
 -                                              Table.RecordCache.DisposeRecord(Original);\r
 -                                      }\r
 -                                      Original = Current;\r
 -                              break;\r
 -                      case DataRowState.Deleted:\r
 -                              _table.Rows.RemoveInternal (this);\r
 -                              DetachRow();\r
 -                              break;\r
 -                      case DataRowState.Detached:\r
 -                              throw new RowNotInTableException("Cannot perform this operation on a row not in the table.");\r
 -                      }\r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Begins an edit operation on a DataRow object.\r
 -              /// </summary>\r
 -              public void BeginEdit () \r
 -              {\r
 -                      if (_inChangingEvent)\r
 -                                 throw new InRowChangingEventException("Cannot call BeginEdit inside an OnRowChanging event.");\r
 -                      if (RowState == DataRowState.Deleted)\r
 -                              throw new DeletedRowInaccessibleException ();\r
 - \r
 -                      if (!HasVersion (DataRowVersion.Proposed)) {\r
 -                              Proposed = Table.RecordCache.NewRecord();\r
 -                              int from = HasVersion(DataRowVersion.Current) ? Current : Table.DefaultValuesRowIndex;\r
 -                              for(int i = 0; i < Table.Columns.Count; i++){\r
 -                                      DataColumn column = Table.Columns[i];\r
 -                                      column.DataContainer.CopyValue(from,Proposed);\r
 -                              }\r
 -                      }\r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Cancels the current edit on the row.\r
 -              /// </summary>\r
 -              public void CancelEdit () \r
 -              {\r
 -                       if (_inChangingEvent) {\r
 -                                 throw new InRowChangingEventException("Cannot call CancelEdit inside an OnRowChanging event.");\r
 -                       }\r
 - \r
 -                      if (HasVersion (DataRowVersion.Proposed)) {\r
 -                              Table.RecordCache.DisposeRecord(Proposed);\r
 -                              Proposed = -1;\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.Clear();\r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Deletes the DataRow.\r
 -              /// </summary>\r
 -              public void Delete () \r
 -              {\r
 -                      _table.DeletingDataRow(this, DataRowAction.Delete);\r
 -                      switch (RowState) {\r
 -                      case DataRowState.Added:\r
 -                              // check what to do with child rows\r
 -                              CheckChildRows(DataRowAction.Delete);\r
 -                              _table.DeleteRowFromIndexes (this);\r
 -                              Table.Rows.RemoveInternal (this);\r
 - \r
 -                              // if row was in Added state we move it to Detached.\r
 -                              DetachRow();\r
 -                              break;\r
 -                      case DataRowState.Deleted:\r
 -                              break;          \r
 -                      default:\r
 -                              // check what to do with child rows\r
 -                              CheckChildRows(DataRowAction.Delete);\r
 -                              _table.DeleteRowFromIndexes (this);\r
 -                              break;\r
 -                      }\r
 -                      if (Current >= 0) {\r
 -                              if (Current != Original) {\r
 -                                      _table.RecordCache.DisposeRecord(Current);\r
 -                              }\r
 -                              Current = -1;\r
 -                      }\r
 -                      _table.DeletedDataRow(this, DataRowAction.Delete);\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 relation 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 ForeignKeyConstrain of the table.\r
 -                                      foreach (Constraint constraint in table.Constraints) {\r
 -                                              if (constraint is ForeignKeyConstraint) { \r
 -                                                      ForeignKeyConstraint fk = (ForeignKeyConstraint) constraint;\r
 -                                                      if (fk.RelatedTable == _table) {\r
 -                                                              switch (action) {\r
 -                                                                      case DataRowAction.Delete:\r
 -                                                                              CheckChildRows(fk, action, fk.DeleteRule);\r
 -                                                                              break;\r
 -                                                                      case DataRowAction.Commit:\r
 -                                                                      case DataRowAction.Rollback:\r
 -                                                                              if (fk.AcceptRejectRule != AcceptRejectRule.None)\r
 -                                                                                      CheckChildRows(fk, action, Rule.Cascade);\r
 -                                                                              break;\r
 -                                                                      default:\r
 -                                                                              CheckChildRows(fk, action, fk.UpdateRule);\r
 -                                                                              break;\r
 -                                                              }\r
 -                                                      }                       \r
 -                                              }                       \r
 -                                      }\r
 -                              }\r
 -                      }\r
 -              }\r
 - \r
 -              private void CheckChildRows(ForeignKeyConstraint fkc, DataRowAction action, Rule rule)\r
 -              {                               \r
 -                      DataRow[] childRows = GetChildRows(fkc, DataRowVersion.Current);\r
 -                      switch (rule)\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
 -                                                      switch(action) {\r
 -                                                              case DataRowAction.Delete: {\r
 -                                                              if (childRows[j].RowState != DataRowState.Deleted)\r
 -                                                                      childRows[j].Delete();\r
 - \r
 -                                                                      break;\r
 -                                                      }\r
 -                                                      // if action is change we change the values in the child row\r
 -                                                              case DataRowAction.Change: {\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 < fkc.Columns.Length; k++)\r
 -                                                                      childRows[j][fkc.Columns[k]] = this[fkc.RelatedColumns[k], DataRowVersion.Proposed];\r
 - \r
 -                                                                      break;\r
 -                                                              }\r
 - \r
 -                                                              case DataRowAction.Rollback: {\r
 -                                                                      if (childRows[j].RowState != DataRowState.Unchanged)\r
 -                                                                              childRows[j].RejectChanges ();\r
 - \r
 -                                                                      break;\r
 -                                                              }\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 " + fkc.ConstraintName +", and changing this row will strand child rows.";\r
 -                                                              string delStr = "Cannot delete this row because constraints are enforced on relation " + fkc.ConstraintName +", 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 && childRows.Length > 0) {\r
 -                                              int defaultValuesRowIndex = childRows[0].Table.DefaultValuesRowIndex;\r
 -                                              foreach(DataRow childRow in childRows) {\r
 -                                                      if (childRow.RowState != DataRowState.Deleted) {\r
 -                                                              int defaultIdx = childRow.IndexFromVersion(DataRowVersion.Default);\r
 -                                                              foreach(DataColumn column in fkc.Columns) {\r
 -                                                                      column.DataContainer.CopyValue(defaultValuesRowIndex,defaultIdx);\r
 -                                                              }\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 < fkc.Columns.Length; k++)\r
 -                                                                      child.SetNull(fkc.Columns[k]);\r
 -                                                      }\r
 -                                              }\r
 -                                      }\r
 -                                      break;\r
 -                      }\r
 - \r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Ends the edit occurring on the row.\r
 -              /// </summary>\r
 -              public void EndEdit () \r
 -              {\r
 -                      if (_inChangingEvent)\r
 -                              throw new InRowChangingEventException("Cannot call EndEdit inside an OnRowChanging event.");\r
 - \r
 -                      if (RowState == DataRowState.Detached)\r
 -                              return;\r
 -                      \r
 -                      if (HasVersion (DataRowVersion.Proposed))\r
 -                      {\r
 -                              CheckReadOnlyStatus();\r
 - \r
 -                              _inChangingEvent = true;\r
 -                              try\r
 -                              {\r
 -                                      _table.ChangingDataRow(this, DataRowAction.Change);\r
 -                              }\r
 -                              finally\r
 -                              {\r
 -                                      _inChangingEvent = false;\r
 -                              }\r
 -                              \r
 -                              //Calling next method validates UniqueConstraints\r
 -                              //and ForeignKeys.\r
 -                              bool rowValidated = false;\r
 -                              try\r
 -                              {\r
 -                                      if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad) {\r
 -                                              _table.Rows.ValidateDataRowInternal(this);\r
 -                                              rowValidated = true;\r
 -                                      }\r
 -                              }\r
 -                              catch (Exception e)\r
 -                              {\r
 -                                      Table.RecordCache.DisposeRecord(Proposed);\r
 -                                      Proposed = -1;\r
 -                                      throw e;\r
 -                              }\r
 - \r
 -                                      CheckChildRows(DataRowAction.Change);\r
 -                              if (Original != Current) {\r
 -                                      Table.RecordCache.DisposeRecord(Current);\r
 -                              }\r
 - \r
 -                              Current = Proposed;\r
 -                              Proposed = -1;\r
 - \r
 -                              if (!rowValidated) {\r
 -                                      // keep indexes updated even if there was no need to validate row\r
 -                                      foreach(Index index in Table.Indexes) {\r
 -                                              index.Update(this,Current); //FIXME: why Current ?!\r
 -                                      }\r
 -                              }\r
 - \r
 -                              // Note : row state must not be changed before all the job on indexes finished,\r
 -                              // since the indexes works with recods rather than with rows and the decision\r
 -                              // which of row records to choose depends on row state.\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.Default);\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 Table.NewRowArray(0);\r
 - \r
 -                      if (this.Table == null)\r
 -                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");\r
 - \r
 -                      if (relation.DataSet != this.Table.DataSet)\r
 -                              throw new ArgumentException();\r
 - \r
 -                      if (_table != relation.ParentTable)\r
 -                              throw new InvalidConstraintException ("GetChildRow requires a row whose Table is " + relation.ParentTable + ", but the specified row's table is " + _table);\r
 - \r
 -                      if (relation.ChildKeyConstraint != null)\r
 -                              return GetChildRows (relation.ChildKeyConstraint, version);\r
 - \r
 -                      ArrayList rows = new ArrayList();\r
 -                      DataColumn[] parentColumns = relation.ParentColumns;\r
 -                      DataColumn[] childColumns = relation.ChildColumns;\r
 -                      int numColumn = parentColumns.Length;\r
 -                      DataRow[] result = null;\r
 - \r
 -                      int versionIndex = IndexFromVersion(version);\r
 -                      int tmpRecord = relation.ChildTable.RecordCache.NewRecord();\r
 - \r
 -                      try {\r
 -                              for (int i = 0; i < numColumn; i++) {\r
 -                                      // according to MSDN: the DataType value for both columns must be identical.\r
 -                                      childColumns[i].DataContainer.CopyValue(parentColumns[i].DataContainer, versionIndex, tmpRecord);\r
 -                              }\r
 - \r
 -                              Index index = relation.ChildTable.FindIndex(childColumns);\r
 - \r
 -                              if (index != null) {\r
 -                                      int[] records = index.FindAll(tmpRecord);\r
 -                                      result = relation.ChildTable.NewRowArray(records.Length);\r
 -                                      for(int i=0; i < records.Length; i++) {\r
 -                                              result[i] = relation.ChildTable.RecordCache[records[i]];\r
 -                                      }\r
 -                              }\r
 -                              else {\r
 -                                      foreach (DataRow row in relation.ChildTable.Rows) {\r
 -                                              bool allColumnsMatch = false;\r
 -                                              if (row.HasVersion(DataRowVersion.Default)) {\r
 -                                                      allColumnsMatch = true;\r
 -                                                      int childIndex = row.IndexFromVersion(DataRowVersion.Default);\r
 -                                                      for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) {\r
 -                                                              if (childColumns[columnCnt].DataContainer.CompareValues(childIndex, tmpRecord) != 0) {\r
 -                                                              allColumnsMatch = false;\r
 -                                                              break;\r
 -                                                      }\r
 -                                              }\r
 -                                      }\r
 -                                      if (allColumnsMatch) rows.Add(row);\r
 -                              }\r
 -                                      result = relation.ChildTable.NewRowArray(rows.Count);\r
 -                                      rows.CopyTo(result, 0);\r
 -                              }\r
 -                      }\r
 -                      finally {\r
 -                              relation.ChildTable.RecordCache.DisposeRecord(tmpRecord);\r
 -                      }                       \r
 - \r
 -                      return result;\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
 -              private DataRow[] GetChildRows (ForeignKeyConstraint fkc, DataRowVersion version) \r
 -              {\r
 -                      ArrayList rows = new ArrayList();\r
 -                      DataColumn[] parentColumns = fkc.RelatedColumns;\r
 -                      DataColumn[] childColumns = fkc.Columns;\r
 -                      int numColumn = parentColumns.Length;\r
 - \r
 -                              Index index = fkc.Index;\r
 - \r
 -                      int curIndex = IndexFromVersion(version);\r
 -                      int tmpRecord = fkc.Table.RecordCache.NewRecord();\r
 -                      for (int i = 0; i < numColumn; i++) {\r
 -                              // according to MSDN: the DataType value for both columns must be identical.\r
 -                              childColumns[i].DataContainer.CopyValue(parentColumns[i].DataContainer, curIndex, tmpRecord);\r
 -                      }\r
 - \r
 -                      try {\r
 -                              if (index != null) {\r
 -                                      // get the child rows from the index\r
 -                                      int[] childRecords = index.FindAll(tmpRecord);\r
 -                                      for (int i = 0; i < childRecords.Length; i++) {\r
 -                                              rows.Add (childColumns[i].Table.RecordCache[childRecords[i]]);\r
 -                                      }\r
 -                              }\r
 -                              else { // if there is no index we search manualy.\r
 -                                              foreach (DataRow row in fkc.Table.Rows) {\r
 -                                                      bool allColumnsMatch = false;\r
 -                                                      if (row.HasVersion(DataRowVersion.Default)) {\r
 -                                                              allColumnsMatch = true;\r
 -                                                              int childIndex = row.IndexFromVersion(DataRowVersion.Default);\r
 -                                                              for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) {\r
 -                                                                      if (childColumns[columnCnt].DataContainer.CompareValues(childIndex, tmpRecord) != 0) {\r
 -                                                                              allColumnsMatch = false;\r
 -                                                                              break;\r
 -                                                                      }\r
 -                                                              }\r
 -                                                      }\r
 -                                                      if (allColumnsMatch) {\r
 -                                                              rows.Add(row);\r
 -                                                      }\r
 -                                              }\r
 -                                      }\r
 -                      }\r
 -                                      finally {\r
 -                                              fkc.Table.RecordCache.DisposeRecord(tmpRecord);\r
 -                                      }\r
 - \r
 -                      DataRow[] result = fkc.Table.NewRowArray(rows.Count);\r
 -                      rows.CopyTo(result, 0);\r
 -                      return result;\r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Gets the error description of the specified DataColumn.\r
 -              /// </summary>\r
 -              public string GetColumnError (DataColumn column) \r
 -              {\r
 -                      if (column == null)\r
 -                              throw new ArgumentNullException("column");\r
 - \r
 -                      int index = _table.Columns.IndexOf(column);\r
 -                      if (index < 0)\r
 -                              throw new ArgumentException(String.Format("Column '{0}' does not belong to table {1}.", column.ColumnName, Table.TableName));\r
 - \r
 -                      return GetColumnError (index);\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 >= Table.Columns.Count)\r
 -                              throw new IndexOutOfRangeException ();\r
 - \r
 -                      string retVal = null;\r
 -                      if (columnIndex < ColumnErrors.Count) {\r
 -                              retVal = (String) ColumnErrors[columnIndex];\r
 -                      }\r
 -                      return (retVal != null) ? retVal : String.Empty;\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
 -                      int columnOrdinal = 0;\r
 -                      foreach(String columnError in ColumnErrors) {\r
 -                              if (columnError != null && columnError != String.Empty) {\r
 -                                      dataColumns.Add (_table.Columns[columnOrdinal]);\r
 -                              }\r
 -                              columnOrdinal++;\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.Default);\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.Default);\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.Default);\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.Default);\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 Table.NewRowArray(0);\r
 - \r
 -                      if (this.Table == null)\r
 -                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");\r
 - \r
 -                      if (relation.DataSet != this.Table.DataSet)\r
 -                              throw new ArgumentException();\r
 - \r
 -                      if (_table != relation.ChildTable)\r
 -                              throw new InvalidConstraintException ("GetParentRows requires a row whose Table is " + relation.ChildTable + ", but the specified row's table is " + _table);\r
 - \r
 -                      ArrayList rows = new ArrayList();\r
 -                      DataColumn[] parentColumns = relation.ParentColumns;\r
 -                      DataColumn[] childColumns = relation.ChildColumns;\r
 -                      int numColumn = parentColumns.Length;\r
 - \r
 -                      int curIndex = IndexFromVersion(version);\r
 -                                      int tmpRecord = relation.ParentTable.RecordCache.NewRecord();\r
 -                                              for (int i = 0; i < numColumn; i++) {\r
 -                                                      // according to MSDN: the DataType value for both columns must be identical.\r
 -                                                      parentColumns[i].DataContainer.CopyValue(childColumns[i].DataContainer, curIndex, tmpRecord);\r
 -                                              }\r
 - \r
 -                      try {\r
 -                              Index index = relation.ParentTable.FindIndex(parentColumns);\r
 -                              if (index != null) { // get the parent rows from the index\r
 -                                      int[] parentRecords = index.FindAll(tmpRecord);\r
 -                                      for (int i = 0; i < parentRecords.Length; i++) {\r
 -                                              rows.Add (parentColumns[i].Table.RecordCache[parentRecords[i]]);\r
 -                                      }\r
 -                              }\r
 -                              else { // no index so we have to search manualy.\r
 -                                              foreach (DataRow row in relation.ParentTable.Rows) {\r
 -                                                      bool allColumnsMatch = false;\r
 -                                                      if (row.HasVersion(DataRowVersion.Default)) {\r
 -                                                              allColumnsMatch = true;\r
 -                                                              int parentIndex = row.IndexFromVersion(DataRowVersion.Default);\r
 -                                                              for (int columnCnt = 0; columnCnt < numColumn; columnCnt++) {\r
 -                                                                      if (parentColumns[columnCnt].DataContainer.CompareValues(parentIndex, tmpRecord) != 0) {\r
 -                                                                              allColumnsMatch = false;\r
 -                                                                              break;\r
 -                                                                      }\r
 -                                                              }\r
 -                                                      }\r
 -                                                      if (allColumnsMatch) {\r
 -                                                              rows.Add(row);\r
 -                                                      }\r
 -                                              }\r
 -                                      }\r
 -                      }\r
 -                                      finally {\r
 -                                              relation.ParentTable.RecordCache.DisposeRecord(tmpRecord);\r
 -                                      }\r
 - \r
 -                      DataRow[] result = relation.ParentTable.NewRowArray(rows.Count);\r
 -                      rows.CopyTo(result, 0);\r
 -                      return result;\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
 -                              case DataRowVersion.Default:\r
 -                                      return (Proposed >= 0 || Current >= 0);\r
 -                              case DataRowVersion.Proposed:\r
 -                                      return Proposed >= 0;\r
 -                              case DataRowVersion.Current:\r
 -                                      return Current >= 0;\r
 -                              case DataRowVersion.Original:\r
 -                                      return Original >= 0;\r
 -                              default:\r
 -                                      return IndexFromVersion(version) >= 0;\r
 -                      }\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
 -                      return IsNull(column, DataRowVersion.Default);\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
 -                      return IsNull(Table.Columns[columnIndex]);\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
 -                      return IsNull(Table.Columns[columnName]);\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 column.DataContainer.IsNull(IndexFromVersion(version));\r
 -              }\r
 - \r
 -              /// <summary>\r
 -              /// Returns a value indicating whether all of the row columns specified contain a null value.\r
 -              /// </summary>\r
 -              internal bool IsNullColumns(DataColumn[] columns)\r
 -              {\r
 -                      bool allNull = true;\r
 -                      for (int i = 0; i < columns.Length; i++) \r
 -                      {\r
 -                              if (!IsNull(columns[i])) \r
 -                              {\r
 -                                      allNull = false;\r
 -                                      break;\r
 -                              }\r
 -                      }\r
 -                      return allNull;\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 (RowState == DataRowState.Detached)\r
 -                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");\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 (HasVersion(DataRowVersion.Original)) {\r
 -                              if (Current >= 0 && Current != Original) {\r
 -                                      Table.RecordCache.DisposeRecord(Current);\r
 -                              }\r
 -                              CheckChildRows(DataRowAction.Rollback);\r
 - \r
 -                              Current = Original;\r
 -                             \r
 -                              _table.ChangedDataRow (this, DataRowAction.Rollback);\r
 -                              CancelEdit ();\r
 -                              switch (RowState)\r
 -                              {\r
 -                                      case DataRowState.Added:\r
 -                                              _table.DeleteRowFromIndexes (this);\r
 -                                              _table.Rows.RemoveInternal (this);\r
 -                                              break;\r
 -                                      case DataRowState.Modified:\r
 -                                              if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)\r
 -                                                      _table.Rows.ValidateDataRowInternal(this);\r
 -                                              break;\r
 -                                      case DataRowState.Deleted:\r
 -                                              if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)\r
 -                                                      _table.Rows.ValidateDataRowInternal(this);\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
 -                              {\r
 -                                      _table.DeleteRowFromIndexes (this);\r
 -                                      _table.Rows.RemoveInternal (this);\r
 -                                      // if row was in Added state we move it to Detached.\r
 -                                      DetachRow();\r
 -                              }\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 >= Table.Columns.Count)\r
 -                              throw new IndexOutOfRangeException ();\r
 - \r
 -                      while(ColumnErrors.Count < columnIndex) {\r
 -                              ColumnErrors.Add(null);\r
 -                      }\r
 -                      ColumnErrors.Add(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
 -              {\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
 -              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
 -              public void SetParentRow (DataRow parentRow, DataRelation relation) \r
 -              {\r
 -                      if (_table == null || parentRow.Table == null)\r
 -                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");\r
 - \r
 -                      if (parentRow != null && _table.DataSet != parentRow.Table.DataSet)\r
 -                              throw new ArgumentException();\r
 -                      \r
 -                      BeginEdit();\r
 - \r
 -                      IEnumerable relations; \r
 -                      if (relation == null) {\r
 -                              relations = _table.ParentRelations;\r
 -                      }\r
 -                      else {\r
 -                              relations = new DataRelation[] { relation };\r
 -                      }\r
 - \r
 -                      foreach (DataRelation rel in relations)\r
 -                      {\r
 -                              DataColumn[] childCols = rel.ChildColumns;\r
 -                              DataColumn[] parentCols = rel.ParentColumns;\r
 -                              \r
 -                              for (int i = 0; i < parentCols.Length; i++)\r
 -                              {\r
 -                                      if (parentRow == null) {\r
 -                                              childCols[i].DataContainer[Proposed] = DBNull.Value;\r
 -                                      }\r
 -                                      else {\r
 -                                              int defaultIdx = parentRow.IndexFromVersion(DataRowVersion.Default);\r
 -                                              childCols[i].DataContainer.CopyValue(parentCols[i].DataContainer,defaultIdx,Proposed);\r
 -                                      }\r
 -                              }\r
 -                              \r
 -                      }\r
 - \r
 -                      EndEdit();\r
 -              }\r
 -              \r
 -              //Copy all values of this DataRow to the row parameter.\r
 -              internal void CopyValuesToRow(DataRow row)\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
 -                      foreach(DataColumn column in Table.Columns) {\r
 -                              DataColumn targetColumn = row.Table.Columns[column.ColumnName];\r
 -                              //if a column with the same name exists in both rows copy the values\r
 -                              if(targetColumn != null) {\r
 -                                      int index = targetColumn.Ordinal;\r
 -                                      if (HasVersion(DataRowVersion.Original)) {\r
 -                                              if (row.Original < 0) {\r
 -                                                      row.Original = row.Table.RecordCache.NewRecord();\r
 -                                              }\r
 -                                              object val = column[Original];\r
 -                                              row.CheckValue(val, targetColumn);\r
 -                                              targetColumn[row.Original] = val;\r
 -                                      }\r
 -                                      else {\r
 -                                              if (row.Original > 0) {\r
 -                                                      row.Table.RecordCache.DisposeRecord(row.Original);\r
 -                                                      row.Original = -1;\r
 -                                              }\r
 -                                      }\r
 - \r
 -                                      if (HasVersion(DataRowVersion.Current)) {\r
 -                                              if (row.Current < 0) {\r
 -                                                      row.Current = row.Table.RecordCache.NewRecord();\r
 -                                              }\r
 -                                              object val = column[Current];\r
 -                                              row.CheckValue(val, targetColumn);\r
 -                                              targetColumn[row.Current] = val;\r
 -                                      }\r
 -                                      else {\r
 -                                              if (row.Current > 0) {\r
 -                                                      row.Table.RecordCache.DisposeRecord(row.Current);\r
 -                                                      row.Current = -1;\r
 -                                              }\r
 -                                      }\r
 - \r
 -                                      if (HasVersion(DataRowVersion.Proposed)) {\r
 -                                              if (row.Proposed < 0) {\r
 -                                                      row.Proposed = row.Table.RecordCache.NewRecord();\r
 -                                              }\r
 -                                              object val = column[row.Proposed];\r
 -                                              row.CheckValue(val, targetColumn);\r
 -                                              targetColumn[row.Proposed] = val;\r
 -                                      }\r
 -                                      else {\r
 -                                              if (row.Proposed > 0) {\r
 -                                                      row.Table.RecordCache.DisposeRecord(row.Proposed);\r
 -                                                      row.Proposed = -1;\r
 -                                              }\r
 -                                      }\r
 -                              }\r
 -                      }\r
 -                      if (HasErrors) {\r
 -                              CopyErrors(row);\r
 -                      }\r
 -              }\r
 - \r
 -              internal void CopyErrors(DataRow row)\r
 -              {\r
 -                      row.RowError = RowError;\r
 -                      DataColumn[] errorColumns = GetColumnsInError();\r
 -                      foreach(DataColumn col in errorColumns) {\r
 -                              DataColumn targetColumn = row.Table.Columns[col.ColumnName];\r
 -                              row.SetColumnError(targetColumn,GetColumnError(col));\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
 -              internal void CheckNullConstraints()\r
 -              {\r
 -                      if (_nullConstraintViolation) {\r
 -                              if (HasVersion(DataRowVersion.Proposed)) {\r
 -                                      foreach(DataColumn column in Table.Columns) {\r
 -                                              if (IsNull(column) && !column.AllowDBNull) {\r
 -                                                      throw new NoNullAllowedException(_nullConstraintMessage);\r
 -                                      }\r
 -                              }\r
 -                              }\r
 -                              _nullConstraintViolation = false;\r
 -                      }\r
 -              }\r
 -              \r
 -              internal void CheckReadOnlyStatus() {\r
 -                              int defaultIdx = IndexFromVersion(DataRowVersion.Default); \r
 -                              foreach(DataColumn column in Table.Columns) {\r
 -                              if ((column.DataContainer.CompareValues(defaultIdx,Proposed) != 0) && column.ReadOnly) {\r
 -                                      throw new ReadOnlyException();\r
 -                         }\r
 -                 }\r
 -                      }                       \r
 -      \r
 -              #endregion // Methods\r
 -      }\r
 - }\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>
 ++//   Sureshkumar T <tsureshkumar@novell.com>
 + //
 + // (C) Ximian, Inc 2002
 + // (C) Daniel Morgan 2002, 2003
 + // Copyright (C) 2002 Tim Coleman
 + //
 + 
 + //
 + // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
 + //
 + // Permission is hereby granted, free of charge, to any person obtaining
 + // a copy of this software and associated documentation files (the
 + // "Software"), to deal in the Software without restriction, including
 + // without limitation the rights to use, copy, modify, merge, publish,
 + // distribute, sublicense, and/or sell copies of the Software, and to
 + // permit persons to whom the Software is furnished to do so, subject to
 + // the following conditions:
 + // 
 + // The above copyright notice and this permission notice shall be
 + // included in all copies or substantial portions of the Software.
 + // 
 + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 + // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 + // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 + // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 + // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 + // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 + //
 + 
 + using System;
 ++using System.Data.Common;
 + using System.Collections;
 + using System.Globalization;
 + using System.Xml;
 + 
++ using System.Data.Common;
++ 
 + namespace System.Data {
 +      /// <summary>
 +      /// Represents a row of data in a DataTable.
 +      /// </summary>
 +      [Serializable]
 +      public class DataRow
 +      {
 +              #region Fields
 + 
 +              private DataTable _table;
 + 
 +              internal int _original = -1;
 +              internal int _current = -1;
 +              internal int _proposed = -1;
 + 
 +              private ArrayList _columnErrors;
 +              private string rowError;
-               private DataRowState rowState;
 +              internal int xmlRowID = 0;
 +              internal bool _nullConstraintViolation;
 +              private string _nullConstraintMessage;
-               private bool editing = false;
 +              private bool _hasParentCollection;
 +              private bool _inChangingEvent;
 +              private int _rowId;
 + 
 +              private XmlDataDocument.XmlDataElement mappedElement;
 +              internal bool _inExpressionEvaluation = false;
 + 
 +              #endregion // Fields
 + 
 +              #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;
 +                      // Get the row id from the builder.
 +                      _rowId = builder._rowId;
 + 
-                       _proposed = _table.RecordCache.NewRecord();
-                       // Initialise the data columns of the row with the dafault values, if any 
-                       // TODO : should proposed version be available immediately after record creation ?
-                       foreach(DataColumn column in _table.Columns) {
-                               column.DataContainer.CopyValue(_table.DefaultValuesRowIndex,_proposed);
-                       }
-                       
 +                      rowError = String.Empty;
 + 
-                       //on first creating a DataRow it is always detached.
-                       rowState = DataRowState.Detached;
-                       
-                       ArrayList aiColumns = _table.Columns.AutoIncrmentColumns;
-                       foreach (DataColumn dc in aiColumns) {
-                               this [dc] = dc.AutoIncrementValue();
-                       }
-  
 +                      // create mapped XmlDataElement
 +                      DataSet ds = _table.DataSet;
 +                      if (ds != null && ds._xmlDataDocument != null)
 +                              mappedElement = new XmlDataDocument.XmlDataElement (this, _table.Prefix, _table.TableName, _table.Namespace, ds._xmlDataDocument);
 +              }
 + 
 +              internal DataRow(DataTable table,int rowId)
 +              {
 +                      _table = table;
 +                      _rowId = rowId;
 +              }
 + 
 +              #endregion // Constructors
 + 
 +              #region Properties
 + 
 +              private ArrayList ColumnErrors
 +              {
 +                      get {
 +                              if (_columnErrors == null) {
 +                                      _columnErrors = new ArrayList();
 +                              }
 +                              return _columnErrors;
 +                      }
 + 
 +                      set {
 +                              _columnErrors = value;
 +                      }
 +              }
 + 
 +              /// <summary>
 +              /// Gets a value indicating whether there are errors in a row.
 +              /// </summary>
 +              public bool HasErrors {
 +                      get {
 +                              if (RowError != string.Empty)
 +                                      return true;
 + 
 +                              foreach(String columnError in ColumnErrors) {
 +                                      if (columnError != null && columnError != 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)
++                              if (RowState == DataRowState.Deleted)
 +                                      throw new DeletedRowInaccessibleException ();
 + 
 +                              DataColumn column = _table.Columns[columnIndex];
 +                              _table.ChangingDataColumn (this, column, value);
 +                              
 +                              if (value == null && column.DataType != typeof(string)) {
 +                                      throw new ArgumentException("Cannot set column " + column.ColumnName + " to be null, Please use DBNull instead");
 +                              }
 +                              
 +                              CheckValue (value, column);
 + 
-                               bool orginalEditing = editing;
++                              bool orginalEditing = Proposed >= 0;
 +                              if (!orginalEditing) {
 +                                      BeginEdit ();
 +                              }
 +                              
-                               column[_proposed] = value;
++                              column[Proposed] = value;
 +                              _table.ChangedDataColumn (this, column, value);
 +                              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 {
 +                              if (column.Table != Table)
 +                                      throw new ArgumentException ("The column does not belong to this table.");
 +                              int columnIndex = column.Ordinal;
 +                              return this[columnIndex, version];
 +                      }
 +              }
 + 
-                  /// <summary>
-                  /// Sets the index into the container records for the original version. Apart
-                  /// from that, it makes sure it pools the record used earlier if they are not
-                  /// used by other versions.
-                  /// </summary>
-                  internal int Original 
-                  {
-                          get { return _original;}
-                          set {
-                                  if (_original == value) 
-                                          return;
-                                  
-                                  if (_original >= 0 
-                                      && _current != _original
-                                      && _proposed != _original)
-                                          Table.RecordCache.DisposeRecord (_original);
-                                  _original = value;
-                          }
-                  }
-  
-                  /// <summary>
-                  /// Sets the index into the container records for the proposed version. Apart
-                  /// from that, it makes sure it pools the record used earlier if they are not
-                  /// used by other versions.
-                  internal int Proposed
-                  {
-                          get { return _proposed;}
-                          set {
-                                  if (_proposed == value)
-                                          return;
-                                  if (_proposed >= 0
-                                      && _proposed != _current
-                                      && _proposed != _original)
-                                          Table.RecordCache.DisposeRecord (_proposed);
-                                  _proposed = value;
-                          }
-                  }
-  
-                  /// <summary>
-                  /// Sets the index into the container records for the current version. Apart
-                  /// from that, it makes sure it pools the record used earlier if they are not
-                  /// used by other versions.
-                  internal int Current 
-                  {
-                          get { return _current;}
-                          set {
-                                  if (_current == value)
-                                          return;
-                                  if (_current >= 0
-                                      && _current != _original
-                                      && _current != _proposed)
-                                          Table.RecordCache.DisposeRecord (_current);
-                                  _current = value;
-                          }
-                  }
-  
 ++                /// <summary>
 ++                /// Set a value for the column into the offset specified by the version.<br>
 ++                /// If the value is auto increment or null, necessary auto increment value
 ++                /// or the default value will be used.
 ++                /// </summary>
 ++                internal void SetValue (int column, object value, int version)
 ++                {
 ++                        DataColumn dc = Table.Columns[column];
 ++
 ++                        if (value == null && ! dc.AutoIncrement) // set default value / auto increment
 ++                                value = dc.DefaultValue;
 ++
 ++                     Table.ChangingDataColumn (this, dc, value);     
 ++                        CheckValue (value, dc);
 ++                        if ( ! dc.AutoIncrement)
 ++                                dc [version] = value;
 ++                        else if (_proposed >= 0 && _proposed != version) // proposed holds the AI
 ++                                dc [version] = dc [_proposed];
 ++                }
 ++
 +              /// <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 (!_inExpressionEvaluation && rowState == DataRowState.Deleted && version != DataRowVersion.Original)
++                              if (!_inExpressionEvaluation && RowState == DataRowState.Deleted && version != DataRowVersion.Original)
 +                                      throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");
 +                              
 +                              DataColumn column = _table.Columns[columnIndex];
++                              int recordIndex = IndexFromVersion(version);
++ 
 +                              if (column.Expression != String.Empty) {
 +                                      object o = column.CompiledExpression.Eval (this);
-                                       return Convert.ChangeType (o, column.DataType);
++                                      if (o != null && o != DBNull.Value) {
++                                              o = Convert.ChangeType (o, column.DataType);
++                                      }
++                                      column[recordIndex] = o;
++                                      return column[recordIndex];
 +                              }
 + 
-                               if (rowState == DataRowState.Detached && version == DataRowVersion.Default && _proposed < 0)
++                              if (RowState == DataRowState.Detached && version == DataRowVersion.Default && Proposed < 0)
 +                                      throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
 +                              
-                               int recordIndex = IndexFromVersion(version);
-  
-                               if (recordIndex >= 0) {
-                                       return column[recordIndex];
-                               }
-                               
-                               throw new VersionNotFoundException (Locale.GetText ("There is no " + version.ToString () + " data to access."));
++                              return column[recordIndex];
 +                      }
 +              }
 +              
 +              /// <summary>
 +              /// Gets or sets all of the values for this row through an array.
 +              /// </summary>
 +              public object[] ItemArray {
 +                      get { 
 +                              // row not in table
-                               if (rowState == DataRowState.Detached)
++                              if (RowState == DataRowState.Detached)
 +                                      throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
 +                              // Accessing deleted rows
-                               if (rowState == DataRowState.Deleted)
++                              if (RowState == DataRowState.Deleted)
 +                                      throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");
 +                              
 +                              object[] items = new object[_table.Columns.Count];
 +                              foreach(DataColumn column in _table.Columns) {
-                                       items[column.Ordinal] = column[_current];
++                                      items[column.Ordinal] = column[Current];
 +                              }
 +                              return items;
 +                      }
 +                      set {
 +                              if (value.Length > _table.Columns.Count)
 +                                      throw new ArgumentException ();
 + 
-                               if (rowState == DataRowState.Deleted)
++                              if (RowState == DataRowState.Deleted)
 +                                      throw new DeletedRowInaccessibleException ();
 +                              
-                               bool orginalEditing = editing;
-                               if (!orginalEditing) { 
-                                       BeginEdit ();
-                               }
-                               object newVal = null;
++                              BeginEdit ();
++ 
 +                              DataColumnChangeEventArgs e = new DataColumnChangeEventArgs();
 +                              foreach(DataColumn column in _table.Columns) {
 +                                      int i = column.Ordinal;
-                                       newVal = (i < value.Length) ? value[i] : null;
++                                      object newVal = (i < value.Length) ? value[i] : null;
++ 
++                                      if (newVal == null)
++                                              continue;
 +                                      
 +                                      e.Initialize(this, column, newVal);
-                                       _table.RaiseOnColumnChanged(e);
 +                                      CheckValue (e.ProposedValue, column);
-                                       column[_proposed] = e.ProposedValue;
-                               }
-                               if (!orginalEditing) {
-                                       EndEdit ();
++                                      _table.RaiseOnColumnChanging(e);
++                                      column[Proposed] = e.ProposedValue;
++                                      _table.RaiseOnColumnChanged(e);
 +                              }
++                              
++                              EndEdit ();
 +                      }
 +              }
 + 
-               internal bool IsEditing {
-                       get { return editing; }
-               }
-  
 +              /// <summary>
 +              /// Gets the current state of the row in regards to its relationship to the
 +              /// DataRowCollection.
 +              /// </summary>
 +              public DataRowState RowState {
 +                      get { 
-                               return rowState; 
++                              //return rowState; 
++                                if ((Original == -1) && (Current == -1))
++                                      {
++                                              return DataRowState.Detached;
++                                      }
++                                      if (Original == Current)
++                                      {
++                                              return DataRowState.Unchanged;
++                                      }
++                                      if (Original == -1)
++                                      {
++                                              return DataRowState.Added;
++                                      }
++                                      if (Current == -1)
++                                      {
++                                              return DataRowState.Deleted;
++                                      }
++                                      return DataRowState.Modified;
 +                      }
 +              }
 + 
 +              /// <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; 
 +                      }
 +              }
 +              
 +              /// <summary>
 +              /// Gets and sets index of row.
 +              // </summary>
 +              internal int RowID {
 +                      get { 
 +                              return _rowId; 
 +                      }
 +                      set { 
 +                              _rowId = value; 
 +                      }
 +              }
 + 
-               #endregion // Properties
++              internal int Original
++              {
++                      get {
++                              return _original;
++                      }
++                      set {
++                              if (Table != null) {
++                                      //Table.RecordCache[_original] = null;
++                                      Table.RecordCache[value] = this;
++                              }
++                              _original = value;
++                      }
++              }
++ 
++              internal int Current
++              {
++                      get {
++                              return _current;
++                      }
++                      set {
++                              if (Table != null) {
++                                      //Table.RecordCache[_current] = null;
++                                      Table.RecordCache[value] = this;
++                              }
++                              _current = value;
++                      }
++              }
++ 
++              internal int Proposed
++              {
++                      get {
++                              return _proposed;
++                      }
++                      set {
++                              if (Table != null) {
++                                      //Table.RecordCache[_proposed] = null;
++                                      Table.RecordCache[value] = this;
++                              }
++                              _proposed = value;
++                      }
++              }
++ 
++              #endregion
 + 
 +              #region Methods
 + 
 +              //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() {
-                       if (_current >= 0) {
-                               Table.RecordCache.DisposeRecord(_current);
++                      if (Proposed != -1) {
++                              if (Current >= 0) {
++                                      Table.RecordCache.DisposeRecord(Current);
++                              }
++                              Current = Proposed;
++                              Proposed = -1;
 +                      }
-                       _current = _proposed;
-                       _proposed = -1;
-                       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() {
-                       if (_proposed >= 0) {
-                               _table.RecordCache.DisposeRecord(_proposed);
-                               _proposed = -1;
++                      if (Proposed >= 0) {
++                              _table.RecordCache.DisposeRecord(Proposed);
++                              if (Proposed == Current) {
++                                      Current = -1;
++                              }
++                              if (Proposed == Original) {
++                                      Original = -1;
++                              }
++                              Proposed = -1;
++                      }
++ 
++                      if (Current >= 0) {
++                              _table.RecordCache.DisposeRecord(Current);
++                              if (Current == Original) {
++                                      Original = -1;
++                              }
++                              Current = -1;
 +                      }
++ 
++                      if (Original >= 0) {
++                              _table.RecordCache.DisposeRecord(Original);
++                              Original = -1;
++                      }
++ 
 +                      _rowId = -1;
 +                      _hasParentCollection = false;
-                       rowState = DataRowState.Detached;
++              }
++ 
++              internal void ImportRecord(int record)
++              {
++                      if (HasVersion(DataRowVersion.Proposed)) {
++                              Table.RecordCache.DisposeRecord(Proposed);
++                      }
++ 
++                      Proposed = record;
++ 
++                      foreach(DataColumn column in Table.Columns.AutoIncrmentColumns) {
++                              column.UpdateAutoIncrementValue(column.DataContainer.GetInt64(Proposed));
++                      }
++ 
 +              }
 + 
 +              private void CheckValue (object v, DataColumn col) 
 +              {               
 +                      if (_hasParentCollection && col.ReadOnly) {
 +                              throw new ReadOnlyException ();
 +                      }
 + 
 +                      if (v == null || v == DBNull.Value) {
 +                              if (col.AllowDBNull || col.AutoIncrement || col.DefaultValue != DBNull.Value) {
 +                                      return;
 +                              }
 + 
 +                              //Constraint violations during data load is raise in DataTable EndLoad
 +                              this._nullConstraintViolation = true;
 +                              if (this.Table._duringDataLoad) {
 +                                      this.Table._nullConstraintViolationDuringDataLoad = true;
 +                              }
 +                              _nullConstraintMessage = "Column '" + col.ColumnName + "' does not allow nulls.";
 +                      
 +                      }
 +              }
 + 
-               internal void SetValuesFromDataRecord(IDataRecord record, int[] mapping)
-               {
-  //                   bool orginalEditing = editing;
-  //                   if (!orginalEditing) { 
-  //                           BeginEdit ();
-  //                   }
-                       
-                       if (!HasVersion(DataRowVersion.Proposed)) {
-                               _proposed = Table.RecordCache.NewRecord();
-                       }
-  
-                       try {
-                               for(int i=0; i < Table.Columns.Count; i++) {
-                                       DataColumn column = Table.Columns[i];
-                                          if (mapping [i] < 0) { // no mapping
-                                                  if (! column.AutoIncrement)
-                                                          column.DataContainer [_proposed] = column.DefaultValue;
-                                                  continue;
-                                          }
-  
-                                       column.DataContainer.SetItemFromDataRecord(_proposed, record,mapping[i]);
-                                       if ( column.AutoIncrement ) { 
-                                               column.UpdateAutoIncrementValue(column.DataContainer.GetInt64(_proposed));
-                                       }
-                               }
-                       }
-                       catch (Exception e){
-                               Table.RecordCache.DisposeRecord(_proposed);
-                               _proposed = -1;
-                               throw e;
-                       }
-  
-  //                   if (!orginalEditing) {
-  //                           EndEdit ();
-  //                   }
-               }
-  
 +              /// <summary>
 +              /// Gets or sets the custom error description for a row.
 +              /// </summary>
 +              public string RowError {
 +                      get { 
 +                              return rowError; 
 +                      }
 +                      set { 
 +                              rowError = value; 
 +                      }
 +              }
 + 
 +              internal int IndexFromVersion(DataRowVersion version)
 +              {
-                       if (HasVersion(version))
-                       {
-                               int recordIndex;
-                               switch (version) {
-                                       case DataRowVersion.Default:
-                                               if (editing || rowState == DataRowState.Detached) {
-                                                       recordIndex = _proposed;
-                                               }
-                                               else {
-                                                       recordIndex = _current;
-                                               }
-                                               break;
-                                       case DataRowVersion.Proposed:
-                                               recordIndex = _proposed;
-                                               break;
-                                       case DataRowVersion.Current:
-                                               recordIndex = _current;
-                                               break;
-                                       case DataRowVersion.Original:
-                                               recordIndex = _original;
-                                               break;
-                                       default:
-                                               throw new ArgumentException ();
-                               }
-                               return recordIndex;
++                      switch (version) {
++                              case DataRowVersion.Default:
++                                      if (Proposed >= 0)
++                                              return Proposed;
++ 
++                                      if (Current >= 0)
++                                              return Current;
++ 
++                                      if (Original < 0)
++                                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
++ 
++                                      throw new DeletedRowInaccessibleException("Deleted row information cannot be accessed through the row.");
++ 
++                              case DataRowVersion.Proposed:
++                                      return AssertValidVersionIndex(version, Proposed);
++                              case DataRowVersion.Current:
++                                      return AssertValidVersionIndex(version, Current);
++                              case DataRowVersion.Original:
++                                      return AssertValidVersionIndex(version, Original);
++                              default:
++                                      throw new DataException ("Version must be Original, Current, or Proposed.");
 +                      }
-                       return -1;
++              }
++ 
++              private int AssertValidVersionIndex(DataRowVersion version, int index) {
++                      if (index >= 0)
++                              return index;
++ 
++                      throw new VersionNotFoundException(String.Format("There is no {0} data to accces.", version));
++              }
++ 
++              internal DataRowVersion VersionFromIndex(int index) {
++                      if (index < 0)
++                              throw new ArgumentException("Index must not be negative.");
++ 
++                      // the order of ifs matters
++                      if (index == Current)
++                              return DataRowVersion.Current;
++                      if (index == Original)
++                              return DataRowVersion.Original;
++                      if (index == Proposed)
++                              return DataRowVersion.Proposed;
++ 
++                      throw new ArgumentException(String.Format("The index {0} does not belong to this row.", index)  );
 +              }
 + 
 +              internal XmlDataDocument.XmlDataElement DataElement {
 +                      get { return mappedElement; }
 +                      set { mappedElement = value; }
 +              }
 + 
 +              internal void SetOriginalValue (string columnName, object val)
 +              {
 +                      DataColumn column = _table.Columns[columnName];
 +                      _table.ChangingDataColumn (this, column, val);
 +                              
-                       if (_original < 0 || _original == _current) { 
-                               // This really creates a new record version if one does not exist
-                               _original = Table.RecordCache.NewRecord();
++                      if (Original < 0 || Original == Current) { 
++                              Original = Table.RecordCache.NewRecord();
 +                      }
 +                      CheckValue (val, column);
-                       column[_original] = val;
-                       rowState = DataRowState.Modified;
++                      column[Original] = val;
 +              }
 + 
 +              /// <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
 ++
 ++                        _table.ChangingDataRow (this, DataRowAction.Commit);
-                       switch (rowState) {
++                      CheckChildRows(DataRowAction.Commit);
++                      switch (RowState) {
 +                              case DataRowState.Unchanged:
 +                                      return;
 +                      case DataRowState.Added:
 +                      case DataRowState.Modified:
-                               rowState = DataRowState.Unchanged;
++                                      if (Original >= 0) {
++                                              Table.RecordCache.DisposeRecord(Original);
++                                      }
++                                      Original = Current;
 +                              break;
 +                      case DataRowState.Deleted:
 +                              _table.Rows.RemoveInternal (this);
 +                              DetachRow();
 +                              break;
 +                      case DataRowState.Detached:
 +                              throw new RowNotInTableException("Cannot perform this operation on a row not in the table.");
 +                      }
-                       // Accept from detached
-                       if (_original != _current)
-                               Original = Current;
 ++
 ++                        _table.ChangedDataRow (this, DataRowAction.Commit);
 +              }
 + 
 +              /// <summary>
 +              /// Begins an edit operation on a DataRow object.
 +              /// </summary>
 +              public void BeginEdit () 
 +              {
 +                      if (_inChangingEvent)
 +                                 throw new InRowChangingEventException("Cannot call BeginEdit inside an OnRowChanging event.");
-                       if (rowState == DataRowState.Deleted)
++                      if (RowState == DataRowState.Deleted)
 +                              throw new DeletedRowInaccessibleException ();
++ 
 +                      if (!HasVersion (DataRowVersion.Proposed)) {
-                               _proposed = Table.RecordCache.NewRecord();
-                               foreach(DataColumn column in Table.Columns) {
-                                       column.DataContainer.CopyValue(_current,_proposed);
++                              Proposed = Table.RecordCache.NewRecord();
++                              int from = HasVersion(DataRowVersion.Current) ? Current : Table.DefaultValuesRowIndex;
++                              for(int i = 0; i < Table.Columns.Count; i++){
++                                      DataColumn column = Table.Columns[i];
++                                      column.DataContainer.CopyValue(from,Proposed);
 +                              }
 +                      }
-                       // setting editing to true stops validations on the row
-                       editing = true;
 +              }
 + 
 +              /// <summary>
 +              /// Cancels the current edit on the row.
 +              /// </summary>
 +              public void CancelEdit () 
 +              {
-                        if (_inChangingEvent)
++                       if (_inChangingEvent) {
 +                                 throw new InRowChangingEventException("Cannot call CancelEdit inside an OnRowChanging event.");
-                       editing = false;
++                       }
++ 
 +                      if (HasVersion (DataRowVersion.Proposed)) {
-                               Table.RecordCache.DisposeRecord(_proposed);
-                               _proposed = -1;
-                               if (rowState == DataRowState.Modified) {
-                                   rowState = DataRowState.Unchanged;
-                               }
++                              Table.RecordCache.DisposeRecord(Proposed);
++                              Proposed = -1;
 +                      }
 +              }
 + 
 +              /// <summary>
 +              /// Clears the errors for the row, including the RowError and errors set with
 +              /// SetColumnError.
 +              /// </summary>
 +              public void ClearErrors () 
 +              {
 +                      rowError = String.Empty;
 +                      ColumnErrors.Clear();
 +              }
 + 
 +              /// <summary>
 +              /// Deletes the DataRow.
 +              /// </summary>
 +              public void Delete () 
 +              {
 +                      _table.DeletingDataRow(this, DataRowAction.Delete);
-                       switch (rowState) {
++                      switch (RowState) {
 +                      case DataRowState.Added:
 +                              // check what to do with child rows
 +                              CheckChildRows(DataRowAction.Delete);
 +                              _table.DeleteRowFromIndexes (this);
 +                              Table.Rows.RemoveInternal (this);
 + 
 +                              // if row was in Added state we move it to Detached.
 +                              DetachRow();
 +                              break;
 +                      case DataRowState.Deleted:
-                          case DataRowState.Detached:
-                               break;
++                              break;          
 +                      default:
 +                              // check what to do with child rows
 +                              CheckChildRows(DataRowAction.Delete);
 +                              _table.DeleteRowFromIndexes (this);
-                               rowState = DataRowState.Deleted;
 +                              break;
 +                      }
++                      if (Current >= 0) {
++                              if (Current != Original) {
++                                      _table.RecordCache.DisposeRecord(Current);
++                              }
++                              Current = -1;
++                      }
 +                      _table.DeletedDataRow(this, DataRowAction.Delete);
 +              }
 + 
 +              // 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 relation 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 ForeignKeyConstrain of the table.
-                                       foreach (ForeignKeyConstraint fk in table.Constraints.ForeignKeyConstraints)
-                                       {
-                                               if (fk.RelatedTable == _table)
-                                               {
-                                                       Rule rule;
-                                                       if (action == DataRowAction.Delete)
-                                                               rule = fk.DeleteRule;
-                                                       else
-                                                               rule = fk.UpdateRule;
-                                                       CheckChildRows(fk, action, rule);
++                                      foreach (Constraint constraint in table.Constraints) {
++                                              if (constraint is ForeignKeyConstraint) { 
++                                                      ForeignKeyConstraint fk = (ForeignKeyConstraint) constraint;
++                                                      if (fk.RelatedTable == _table) {
++                                                              switch (action) {
++                                                                      case DataRowAction.Delete:
++                                                                              CheckChildRows(fk, action, fk.DeleteRule);
++                                                                              break;
++                                                                      case DataRowAction.Commit:
++                                                                      case DataRowAction.Rollback:
++                                                                              if (fk.AcceptRejectRule != AcceptRejectRule.None)
++                                                                                      CheckChildRows(fk, action, Rule.Cascade);
++                                                                              break;
++                                                                      default:
++                                                                              CheckChildRows(fk, action, fk.UpdateRule);
++                                                                              break;
++                                                              }
++                                                      }                       
 +                                              }                       
 +                                      }
 +                              }
 +                      }
 +              }
 + 
 +              private void CheckChildRows(ForeignKeyConstraint fkc, DataRowAction action, Rule rule)
 +              {                               
-                       DataRow[] childRows = GetChildRows(fkc, DataRowVersion.Default);
++                      DataRow[] childRows = GetChildRows(fkc, DataRowVersion.Current);
 +                      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)
-                                                       {
++                                                      switch(action) {
++                                                              case DataRowAction.Delete: {
 +                                                              if (childRows[j].RowState != DataRowState.Deleted)
 +                                                                      childRows[j].Delete();
++ 
++                                                                      break;
 +                                                      }
 +                                                      // if action is change we change the values in the child row
-                                                       else if (action == DataRowAction.Change)
-                                                       {
++                                                              case 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 < fkc.Columns.Length; k++)
 +                                                                      childRows[j][fkc.Columns[k]] = this[fkc.RelatedColumns[k], DataRowVersion.Proposed];
++ 
++                                                                      break;
++                                                              }
++ 
++                                                              case DataRowAction.Rollback: {
++                                                                      if (childRows[j].RowState != DataRowState.Unchanged)
++                                                                              childRows[j].RejectChanges ();
++ 
++                                                                      break;
++                                                              }
 +                                                      }
 +                                              }
 +                                      }
 +                                      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 " + fkc.ConstraintName +", and changing this row will strand child rows.";
 +                                                              string delStr = "Cannot delete this row because constraints are enforced on relation " + fkc.ConstraintName +", 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 && childRows.Length > 0) {
 +                                              int defaultValuesRowIndex = childRows[0].Table.DefaultValuesRowIndex;
 +                                              foreach(DataRow childRow in childRows) {
 +                                                      if (childRow.RowState != DataRowState.Deleted) {
 +                                                              int defaultIdx = childRow.IndexFromVersion(DataRowVersion.Default);
 +                                                              foreach(DataColumn column in fkc.Columns) {
 +                                                                      column.DataContainer.CopyValue(defaultValuesRowIndex,defaultIdx);
 +                                                              }
 +                                                      }
 +                                              }
 +                                      }
 +                                      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 < fkc.Columns.Length; k++)
 +                                                                      child.SetNull(fkc.Columns[k]);
 +                                                      }
 +                                              }
 +                                      }
 +                                      break;
 +                      }
 + 
 +              }
 + 
 +              /// <summary>
 +              /// Ends the edit occurring on the row.
 +              /// </summary>
 +              public void EndEdit () 
 +              {
 +                      if (_inChangingEvent)
 +                              throw new InRowChangingEventException("Cannot call EndEdit inside an OnRowChanging event.");
-                       if (rowState == DataRowState.Detached)
-                       {
-                               editing = false;
++ 
++                      if (RowState == DataRowState.Detached)
 +                              return;
-                       }
 +                      
-                       CheckReadOnlyStatus();
 +                      if (HasVersion (DataRowVersion.Proposed))
 +                      {
++                              CheckReadOnlyStatus();
++ 
 +                              _inChangingEvent = true;
 +                              try
 +                              {
 +                                      _table.ChangingDataRow(this, DataRowAction.Change);
 +                              }
 +                              finally
 +                              {
 +                                      _inChangingEvent = false;
 +                              }
-                               if (rowState == DataRowState.Unchanged)
-                                       rowState = DataRowState.Modified;
 +                              
 +                              //Calling next method validates UniqueConstraints
 +                              //and ForeignKeys.
++                              bool rowValidated = false;
 +                              try
 +                              {
-                                       if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)
++                                      if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad) {
 +                                              _table.Rows.ValidateDataRowInternal(this);
++                                              rowValidated = true;
++                                      }
 +                              }
 +                              catch (Exception e)
 +                              {
-                                       editing = false;
-                                       Table.RecordCache.DisposeRecord(_proposed);
-                                       _proposed = -1;
++                                      Table.RecordCache.DisposeRecord(Proposed);
++                                      Proposed = -1;
 +                                      throw e;
 +                              }
 + 
-                               // Now we are going to check all child rows of current row.
-                               // In the case the cascade is true the child rows will look up for
-                               // parent row. since lookup in index is always on current,
-                               // we have to move proposed version of current row to current
-                               // in the case of check child row failure we are rolling 
-                               // current row state back.
-                               int backup = _current;
-                               _current = _proposed;
-                               bool editing_backup = editing;
-                               editing = false;
-                               try {
-                                       // check all child rows.
 +                                      CheckChildRows(DataRowAction.Change);
-                                       _proposed = -1;
-                                       if (_original != backup) {
-                                               Table.RecordCache.DisposeRecord(backup);
-                                       }
++                              if (Original != Current) {
++                                      Table.RecordCache.DisposeRecord(Current);
 +                              }
-                               catch (Exception ex) {
-                                       // if check child rows failed - rollback to previous state
-                                       // i.e. restore proposed and current versions
-                                       _proposed = _current;
-                                       _current = backup;
-                                       editing = editing_backup;
-                                       // since we failed - propagate an exception
-                                       throw ex;
++ 
++                              Current = Proposed;
++                              Proposed = -1;
++ 
++                              if (!rowValidated) {
++                                      // keep indexes updated even if there was no need to validate row
++                                      foreach(Index index in Table.Indexes) {
++                                              index.Update(this,Current); //FIXME: why Current ?!
++                                      }
 +                              }
++ 
++                              // Note : row state must not be changed before all the job on indexes finished,
++                              // since the indexes works with recods rather than with rows and the decision
++                              // which of row records to choose depends on row state.
 +                              _table.ChangedDataRow(this, DataRowAction.Change);
 +                      }
 +              }
 + 
 +              /// <summary>
 +              /// Gets the child rows of this DataRow using the specified DataRelation.
 +              /// </summary>
 +              public DataRow[] GetChildRows (DataRelation relation) 
 +              {
 +                      return GetChildRows (relation, DataRowVersion.Default);
 +              }
 + 
 +              /// <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];
++                              return Table.NewRowArray(0);
 + 
-                       //if (this.Table == null || RowState == DataRowState.Detached)
 +                      if (this.Table == null)
 +                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
 + 
 +                      if (relation.DataSet != this.Table.DataSet)
 +                              throw new ArgumentException();
 + 
 +                      if (_table != relation.ParentTable)
 +                              throw new InvalidConstraintException ("GetChildRow requires a row whose Table is " + relation.ParentTable + ", but the specified row's table is " + _table);
 + 
 +                      if (relation.ChildKeyConstraint != null)
 +                              return GetChildRows (relation.ChildKeyConstraint, version);
 + 
 +                      ArrayList rows = new ArrayList();
 +                      DataColumn[] parentColumns = relation.ParentColumns;
 +                      DataColumn[] childColumns = relation.ChildColumns;
 +                      int numColumn = parentColumns.Length;
-                       if (HasVersion(version))
-                       {
-                               object[] vals = new object[parentColumns.Length];
-                               for (int i = 0; i < vals.Length; i++)
-                                       vals[i] = this[parentColumns[i], 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 (!vals[columnCnt].Equals(
-                                                               row[childColumns[columnCnt], DataRowVersion.Default])) 
-                                                       {
++                      DataRow[] result = null;
++ 
++                      int versionIndex = IndexFromVersion(version);
++                      int tmpRecord = relation.ChildTable.RecordCache.NewRecord();
++ 
++                      try {
++                              for (int i = 0; i < numColumn; i++) {
++                                      // according to MSDN: the DataType value for both columns must be identical.
++                                      childColumns[i].DataContainer.CopyValue(parentColumns[i].DataContainer, versionIndex, tmpRecord);
++                              }
++ 
++                              Index index = relation.ChildTable.FindIndex(childColumns);
++ 
++                              if (index != null) {
++                                      int[] records = index.FindAll(tmpRecord);
++                                      result = relation.ChildTable.NewRowArray(records.Length);
++                                      for(int i=0; i < records.Length; i++) {
++                                              result[i] = relation.ChildTable.RecordCache[records[i]];
++                                      }
++                              }
++                              else {
++                                      foreach (DataRow row in relation.ChildTable.Rows) {
++                                              bool allColumnsMatch = false;
++                                              if (row.HasVersion(DataRowVersion.Default)) {
++                                                      allColumnsMatch = true;
++                                                      int childIndex = row.IndexFromVersion(DataRowVersion.Default);
++                                                      for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) {
++                                                              if (childColumns[columnCnt].DataContainer.CompareValues(childIndex, tmpRecord) != 0) {
 +                                                              allColumnsMatch = false;
 +                                                              break;
 +                                                      }
 +                                              }
 +                                      }
 +                                      if (allColumnsMatch) rows.Add(row);
 +                              }
-                       }else
-                               throw new VersionNotFoundException("There is no " + version + " data to accces.");
++                                      result = relation.ChildTable.NewRowArray(rows.Count);
++                                      rows.CopyTo(result, 0);
++                              }
++                      }
++                      finally {
++                              relation.ChildTable.RecordCache.DisposeRecord(tmpRecord);
++                      }                       
 + 
-                       DataRow[] result = relation.ChildTable.NewRowArray(rows.Count);
-                       rows.CopyTo(result, 0);
 +                      return result;
 +              }
 + 
 +              /// <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);
 +              }
 + 
 +              private DataRow[] GetChildRows (ForeignKeyConstraint fkc, DataRowVersion version) 
 +              {
 +                      ArrayList rows = new ArrayList();
 +                      DataColumn[] parentColumns = fkc.RelatedColumns;
 +                      DataColumn[] childColumns = fkc.Columns;
 +                      int numColumn = parentColumns.Length;
-                       if (HasVersion(version)) {
++ 
 +                              Index index = fkc.Index;
++ 
++                      int curIndex = IndexFromVersion(version);
++                      int tmpRecord = fkc.Table.RecordCache.NewRecord();
++                      for (int i = 0; i < numColumn; i++) {
++                              // according to MSDN: the DataType value for both columns must be identical.
++                              childColumns[i].DataContainer.CopyValue(parentColumns[i].DataContainer, curIndex, tmpRecord);
++                      }
++ 
++                      try {
 +                              if (index != null) {
 +                                      // get the child rows from the index
-                                       Node[] childNodes = index.FindAllSimple (parentColumns, IndexFromVersion(version));
-                                       for (int i = 0; i < childNodes.Length; i++) {
-                                               rows.Add (childNodes[i].Row);
++                                      int[] childRecords = index.FindAll(tmpRecord);
++                                      for (int i = 0; i < childRecords.Length; i++) {
++                                              rows.Add (childColumns[i].Table.RecordCache[childRecords[i]]);
 +                                      }
 +                              }
 +                              else { // if there is no index we search manualy.
-                                       int curIndex = IndexFromVersion(DataRowVersion.Default);
-                                       int tmpRecord = fkc.Table.RecordCache.NewRecord();
-  
-                                       try {
-                                               for (int i = 0; i < numColumn; i++) {
-                                                       // according to MSDN: the DataType value for both columns must be identical.
-                                                       childColumns[i].DataContainer.CopyValue(parentColumns[i].DataContainer, curIndex, tmpRecord);
-                                               }
-  
 +                                              foreach (DataRow row in fkc.Table.Rows) {
 +                                                      bool allColumnsMatch = false;
 +                                                      if (row.HasVersion(DataRowVersion.Default)) {
 +                                                              allColumnsMatch = true;
 +                                                              int childIndex = row.IndexFromVersion(DataRowVersion.Default);
 +                                                              for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) {
 +                                                                      if (childColumns[columnCnt].DataContainer.CompareValues(childIndex, tmpRecord) != 0) {
 +                                                                              allColumnsMatch = false;
 +                                                                              break;
 +                                                                      }
 +                                                              }
 +                                                      }
 +                                                      if (allColumnsMatch) {
 +                                                              rows.Add(row);
 +                                                      }
 +                                              }
 +                                      }
++                      }
 +                                      finally {
 +                                              fkc.Table.RecordCache.DisposeRecord(tmpRecord);
 +                                      }
-                               }
-                       }else
-                               throw new VersionNotFoundException("There is no " + version + " data to accces.");
 + 
 +                      DataRow[] result = fkc.Table.NewRowArray(rows.Count);
 +                      rows.CopyTo(result, 0);
 +                      return result;
 +              }
 + 
 +              /// <summary>
 +              /// Gets the error description of the specified DataColumn.
 +              /// </summary>
 +              public string GetColumnError (DataColumn column) 
 +              {
-                       return GetColumnError (_table.Columns.IndexOf(column));
++                      if (column == null)
++                              throw new ArgumentNullException("column");
++ 
++                      int index = _table.Columns.IndexOf(column);
++                      if (index < 0)
++                              throw new ArgumentException(String.Format("Column '{0}' does not belong to table {1}.", column.ColumnName, Table.TableName));
++ 
++                      return GetColumnError (index);
 +              }
 + 
 +              /// <summary>
 +              /// Gets the error description for the column specified by index.
 +              /// </summary>
 +              public string GetColumnError (int columnIndex) 
 +              {
 +                      if (columnIndex < 0 || columnIndex >= Table.Columns.Count)
 +                              throw new IndexOutOfRangeException ();
 + 
 +                      string retVal = null;
 +                      if (columnIndex < ColumnErrors.Count) {
 +                              retVal = (String) ColumnErrors[columnIndex];
 +                      }
 +                      return (retVal != null) ? retVal : String.Empty;
 +              }
 + 
 +              /// <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 ();
 + 
 +                      int columnOrdinal = 0;
 +                      foreach(String columnError in ColumnErrors) {
 +                              if (columnError != null && columnError != String.Empty) {
 +                                      dataColumns.Add (_table.Columns[columnOrdinal]);
 +                              }
 +                              columnOrdinal++;
 +                      }
 + 
 +                      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.Default);
 +              }
 + 
 +              /// <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.Default);
 +              }
 + 
 +              /// <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.Default);
 +              }
 + 
 +              /// <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.Default);
 +              }
 + 
 +              /// <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];
++                              return Table.NewRowArray(0);
 + 
 +                      if (this.Table == null)
 +                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
 + 
 +                      if (relation.DataSet != this.Table.DataSet)
 +                              throw new ArgumentException();
 + 
 +                      if (_table != relation.ChildTable)
 +                              throw new InvalidConstraintException ("GetParentRows requires a row whose Table is " + relation.ChildTable + ", but the specified row's table is " + _table);
 + 
 +                      ArrayList rows = new ArrayList();
 +                      DataColumn[] parentColumns = relation.ParentColumns;
 +                      DataColumn[] childColumns = relation.ChildColumns;
 +                      int numColumn = parentColumns.Length;
-                       if (HasVersion(version)) {
-                               Index indx = relation.ParentTable.GetIndexByColumns (parentColumns);
-                               if (indx != null && 
-      (Table == null || Table.DataSet == null || 
-       Table.DataSet.EnforceConstraints)) { // get the child rows from the index
-                                       Node[] childNodes = indx.FindAllSimple(childColumns, IndexFromVersion(version));
-                                       for (int i = 0; i < childNodes.Length; i++) {
-                                               rows.Add (childNodes[i].Row);
-                                       }
-                               }
-                               else { // no index so we have to search manualy.
-                                       int curIndex = IndexFromVersion(DataRowVersion.Default);
++ 
++                      int curIndex = IndexFromVersion(version);
 +                                      int tmpRecord = relation.ParentTable.RecordCache.NewRecord();
-                                       try {
 +                                              for (int i = 0; i < numColumn; i++) {
 +                                                      // according to MSDN: the DataType value for both columns must be identical.
 +                                                      parentColumns[i].DataContainer.CopyValue(childColumns[i].DataContainer, curIndex, tmpRecord);
 +                                              }
 + 
++                      try {
++                              Index index = relation.ParentTable.FindIndex(parentColumns);
++                              if (index != null) { // get the parent rows from the index
++                                      int[] parentRecords = index.FindAll(tmpRecord);
++                                      for (int i = 0; i < parentRecords.Length; i++) {
++                                              rows.Add (parentColumns[i].Table.RecordCache[parentRecords[i]]);
++                                      }
++                              }
++                              else { // no index so we have to search manualy.
 +                                              foreach (DataRow row in relation.ParentTable.Rows) {
 +                                                      bool allColumnsMatch = false;
 +                                                      if (row.HasVersion(DataRowVersion.Default)) {
 +                                                              allColumnsMatch = true;
 +                                                              int parentIndex = row.IndexFromVersion(DataRowVersion.Default);
 +                                                              for (int columnCnt = 0; columnCnt < numColumn; columnCnt++) {
 +                                                                      if (parentColumns[columnCnt].DataContainer.CompareValues(parentIndex, tmpRecord) != 0) {
 +                                                                              allColumnsMatch = false;
 +                                                                              break;
 +                                                                      }
 +                                                              }
 +                                                      }
 +                                                      if (allColumnsMatch) {
 +                                                              rows.Add(row);
 +                                                      }
 +                                              }
 +                                      }
++                      }
 +                                      finally {
 +                                              relation.ParentTable.RecordCache.DisposeRecord(tmpRecord);
 +                                      }
-                               }
-                       }else
-                               throw new VersionNotFoundException("There is no " + version + " data to accces.");
 + 
 +                      DataRow[] result = relation.ParentTable.NewRowArray(rows.Count);
 +                      rows.CopyTo(result, 0);
 +                      return result;
 +              }
 + 
 +              /// <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 && !_inExpressionEvaluation)
-                                          return false;
-                                  if (rowState == DataRowState.Detached)
-                                          return _proposed >= 0;
-                                  return true;
-                          case DataRowVersion.Proposed:
-                                  if (rowState == DataRowState.Deleted && !_inExpressionEvaluation)
-                                          return false;
-                                  return _proposed >= 0;
-                          case DataRowVersion.Current:
-                                  if ((rowState == DataRowState.Deleted && !_inExpressionEvaluation) || rowState == DataRowState.Detached)
-                                          return false;
-                                  return _current >= 0;
-                          case DataRowVersion.Original:
-                                  if (rowState == DataRowState.Detached)
-                                          return false;
-                                  return _original >= 0;
-                          }
-                       return false;
++                      switch (version) {
++                              case DataRowVersion.Default:
++                                      return (Proposed >= 0 || Current >= 0);
++                              case DataRowVersion.Proposed:
++                                      return Proposed >= 0;
++                              case DataRowVersion.Current:
++                                      return Current >= 0;
++                              case DataRowVersion.Original:
++                                      return Original >= 0;
++                              default:
++                                      return IndexFromVersion(version) >= 0;
++                      }
 +              }
 + 
 +              /// <summary>
 +              /// Gets a value indicating whether the specified DataColumn contains a null value.
 +              /// </summary>
 +              public bool IsNull (DataColumn column) 
 +              {
 +                      return IsNull(column, DataRowVersion.Default);
 +              }
 + 
 +              /// <summary>
 +              /// Gets a value indicating whether the column at the specified index contains a null
 +              /// value.
 +              /// </summary>
 +              public bool IsNull (int columnIndex) 
 +              {
 +                      return IsNull(Table.Columns[columnIndex]);
 +              }
 + 
 +              /// <summary>
 +              /// Gets a value indicating whether the named column contains a null value.
 +              /// </summary>
 +              public bool IsNull (string columnName) 
 +              {
 +                      return IsNull(Table.Columns[columnName]);
 +              }
 + 
 +              /// <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 column.DataContainer.IsNull(IndexFromVersion(version));
 +              }
 + 
 +              /// <summary>
 +              /// Returns a value indicating whether all of the row columns specified contain a null value.
 +              /// </summary>
 +              internal bool IsNullColumns(DataColumn[] columns)
 +              {
 +                      bool allNull = true;
 +                      for (int i = 0; i < columns.Length; i++) 
 +                      {
 +                              if (!IsNull(columns[i])) 
 +                              {
 +                                      allNull = false;
 +                                      break;
 +                              }
 +                      }
 +                      return allNull;
 +              }
 + 
 +              /// <summary>
 +              /// Rejects all changes made to the row since AcceptChanges was last called.
 +              /// </summary>
 +              public void RejectChanges () 
 +              {
 +                      if (RowState == DataRowState.Detached)
 +                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
 +                      // If original is null, then nothing has happened since AcceptChanges
 +                      // was last called.  We have no "original" to go back to.
 +                      if (HasVersion(DataRowVersion.Original)) {
-                               if (_current >= 0 ) {
-                                       Table.RecordCache.DisposeRecord(_current);
++                              if (Current >= 0 && Current != Original) {
++                                      Table.RecordCache.DisposeRecord(Current);
 +                              }
-                               _current = _original;
++                              CheckChildRows(DataRowAction.Rollback);
++ 
++                              Current = Original;
 +                             
 +                              _table.ChangedDataRow (this, DataRowAction.Rollback);
 +                              CancelEdit ();
-                               switch (rowState)
++                              switch (RowState)
 +                              {
 +                                      case DataRowState.Added:
 +                                              _table.DeleteRowFromIndexes (this);
 +                                              _table.Rows.RemoveInternal (this);
 +                                              break;
 +                                      case DataRowState.Modified:
 +                                              if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)
 +                                                      _table.Rows.ValidateDataRowInternal(this);
-                                               rowState = DataRowState.Unchanged;
 +                                              break;
 +                                      case DataRowState.Deleted:
-                                               rowState = DataRowState.Unchanged;
 +                                              if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)
 +                                                      _table.Rows.ValidateDataRowInternal(this);
 +                                              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)
++                              if ((RowState & DataRowState.Added) > 0)
 +                              {
 +                                      _table.DeleteRowFromIndexes (this);
 +                                      _table.Rows.RemoveInternal (this);
 +                                      // if row was in Added state we move it to Detached.
 +                                      DetachRow();
 +                              }
 +                      }
 +              }
 + 
 +              /// <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 >= Table.Columns.Count)
 +                              throw new IndexOutOfRangeException ();
 + 
 +                      while(ColumnErrors.Count < columnIndex) {
 +                              ColumnErrors.Add(null);
 +                      }
 +                      ColumnErrors.Add(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>
 +              public void SetParentRow (DataRow parentRow) 
 +              {
 +                      SetParentRow(parentRow, null);
 +              }
 + 
 +              /// <summary>
 +              /// Sets the parent row of a DataRow with specified new parent DataRow and
 +              /// DataRelation.
 +              /// </summary>
 +              public void SetParentRow (DataRow parentRow, DataRelation relation) 
 +              {
 +                      if (_table == null || parentRow.Table == null)
 +                              throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
 + 
 +                      if (parentRow != null && _table.DataSet != parentRow.Table.DataSet)
 +                              throw new ArgumentException();
 +                      
 +                      BeginEdit();
-                       if (relation == null)
-                       {
-                               foreach (DataRelation parentRel in _table.ParentRelations)
-                               {
-                                       DataColumn[] childCols = parentRel.ChildColumns;
-                                       DataColumn[] parentCols = parentRel.ParentColumns;
-                                       
-                                       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]];
-                                       }
-                                       
-                               }
++ 
++                      IEnumerable relations; 
++                      if (relation == null) {
++                              relations = _table.ParentRelations;
++                      }
++                      else {
++                              relations = new DataRelation[] { relation };
 +                      }
-                       else
++ 
++                      foreach (DataRelation rel in relations)
 +                      {
-                               DataColumn[] childCols = relation.ChildColumns;
-                               DataColumn[] parentCols = relation.ParentColumns;
-                                       
++                              DataColumn[] childCols = rel.ChildColumns;
++                              DataColumn[] parentCols = rel.ParentColumns;
++                              
 +                              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]];
++                                      if (parentRow == null) {
++                                              childCols[i].DataContainer[Proposed] = DBNull.Value;
++                                      }
++                                      else {
++                                              int defaultIdx = parentRow.IndexFromVersion(DataRowVersion.Default);
++                                              childCols[i].DataContainer.CopyValue(parentCols[i].DataContainer,defaultIdx,Proposed);
++                                      }
 +                              }
++                              
 +                      }
++ 
 +                      EndEdit();
 +              }
 +              
-               //Copy all values of this DataaRow to the row parameter.
++              //Copy all values of this DataRow 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");
 + 
 +                      foreach(DataColumn column in Table.Columns) {
 +                              DataColumn targetColumn = row.Table.Columns[column.ColumnName];
 +                              //if a column with the same name exists in both rows copy the values
 +                              if(targetColumn != null) {
 +                                      int index = targetColumn.Ordinal;
 +                                      if (HasVersion(DataRowVersion.Original)) {
-                                               if (row._original < 0) {
-                                                       row._original = row.Table.RecordCache.NewRecord();
++                                              if (row.Original < 0) {
++                                                      row.Original = row.Table.RecordCache.NewRecord();
 +                                              }
-                                               object val = column[_original];
++                                              object val = column[Original];
 +                                              row.CheckValue(val, targetColumn);
-                                               targetColumn[row._original] = val;
++                                              targetColumn[row.Original] = val;
++                                      }
++                                      else {
++                                              if (row.Original > 0) {
++                                                      row.Table.RecordCache.DisposeRecord(row.Original);
++                                                      row.Original = -1;
++                                              }
 +                                      }
++ 
 +                                      if (HasVersion(DataRowVersion.Current)) {
-                                               if (row._current < 0) {
-                                                       row._current = row.Table.RecordCache.NewRecord();
++                                              if (row.Current < 0) {
++                                                      row.Current = row.Table.RecordCache.NewRecord();
 +                                              }
-                                               object val = column[_current];
++                                              object val = column[Current];
 +                                              row.CheckValue(val, targetColumn);
-                                               targetColumn[row._current] = val;
++                                              targetColumn[row.Current] = val;
++                                      }
++                                      else {
++                                              if (row.Current > 0) {
++                                                      row.Table.RecordCache.DisposeRecord(row.Current);
++                                                      row.Current = -1;
++                                              }
 +                                      }
++ 
 +                                      if (HasVersion(DataRowVersion.Proposed)) {
-                                               if (row._proposed < 0) {
-                                                       row._proposed = row.Table.RecordCache.NewRecord();
++                                              if (row.Proposed < 0) {
++                                                      row.Proposed = row.Table.RecordCache.NewRecord();
 +                                              }
-                                               object val = column[row._proposed];
++                                              object val = column[row.Proposed];
 +                                              row.CheckValue(val, targetColumn);
-                                               targetColumn[row._proposed] = val;
++                                              targetColumn[row.Proposed] = val;
++                                      }
++                                      else {
++                                              if (row.Proposed > 0) {
++                                                      row.Table.RecordCache.DisposeRecord(row.Proposed);
++                                                      row.Proposed = -1;
++                                              }
 +                                      }
-                                       
-                                          int srcIndex = IndexFromVersion (DataRowVersion.Default);
-                                          if (srcIndex >= 0) {
-                                                  //Saving the current value as the column value
-                                                  // FIXME: no idea why is this required
-                                                  object defaultVal = column [srcIndex];
-                                                  row [index] = defaultVal;
-                                          }
 +                              }
 +                      }
-                       CopyState(row);
++                      if (HasErrors) {
++                              CopyErrors(row);
++                      }
 +              }
 + 
-               // Copy row state - rowState and errors
-               internal void CopyState(DataRow row)
++              internal void CopyErrors(DataRow row)
 +              {
-                       row.rowState = RowState;
 +                      row.RowError = RowError;
-                       row.ColumnErrors = (ArrayList)ColumnErrors.Clone();
++                      DataColumn[] errorColumns = GetColumnsInError();
++                      foreach(DataColumn col in errorColumns) {
++                              DataColumn targetColumn = row.Table.Columns[col.ColumnName];
++                              row.SetColumnError(targetColumn,GetColumnError(col));
++                      }
 +              }
 + 
 +              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()
 +              {
 +                      if (_nullConstraintViolation) {
 +                              if (HasVersion(DataRowVersion.Proposed)) {
 +                                      foreach(DataColumn column in Table.Columns) {
 +                                              if (IsNull(column) && !column.AllowDBNull) {
 +                                                      throw new NoNullAllowedException(_nullConstraintMessage);
 +                                      }
 +                              }
 +                              }
 +                              _nullConstraintViolation = false;
 +                      }
 +              }
 +              
-               internal void CheckReadOnlyStatus()
-                  {
-                       if (HasVersion(DataRowVersion.Proposed)) {
++              internal void CheckReadOnlyStatus() {
 +                              int defaultIdx = IndexFromVersion(DataRowVersion.Default); 
 +                              foreach(DataColumn column in Table.Columns) {
-                                       if ((column.DataContainer.CompareValues(defaultIdx,_proposed) != 0) && column.ReadOnly) {
++                              if ((column.DataContainer.CompareValues(defaultIdx,Proposed) != 0) && column.ReadOnly) {
 +                                      throw new ReadOnlyException();
 +                         }
 +                 }
 +                      }                       
-                  }
-  
-                  /// <summary>
-                  ///     Internal method to get a value of the record. This is a utility 
-                  ///    method to fetch a value without any restriction. The only exception is
-                  ///    when the given index or record index is out of range. That has to be
-                  ///    handled by the caller.
-                  /// </summary>
-                  internal object GetValue (int index, int record)
-                  {
-                          return Table.Columns [index] [record];
-                  }
-  
-                  /// <summary>
-                  ///     Internal method to get a value of the record for a given version. 
-                  ///    This is a utility to fetch a value without any restriction.
-                  /// </summary>
-                  /// <exception type="VersionNotFoundException">
-                  ///     if the row does not have version will throw exception
-                  /// </exception>
-                  internal object GetValue (int index, DataRowVersion version)
-                  {
-                          int record = IndexFromVersion (version); // returns -1 if version not found
-                          if (record < 0)
-                                  throw new VersionNotFoundException (String.Format ("This row does not have" +
-                                                                                     " version {0}.",
-                                                                                     version)
-                                                                      );
-                          return GetValue (index, record);
-                  }
-                  
-  
 +      
 +              #endregion // Methods
 ++
 ++#if NET_2_0
 ++                /// <summary>
 ++                ///    This method loads a given value into the existing row affecting versions,
 ++                ///    state based on the LoadOption.  The matrix of changes for this method are as
 ++                ///    mentioned in the DataTable.Load (IDataReader, LoadOption) method.
 ++                /// </summary>
 ++                [MonoTODO ("Raise necessary Events")]
 ++                internal void Load (object [] values, LoadOption loadOption, bool is_new)
 ++                {
 ++                        DataRowAction action = DataRowAction.Change;
 ++
 ++                        int temp = Table.RecordCache.NewRecord ();
 ++                        for (int i = 0 ; i < Table.Columns.Count; i++)
 ++                                SetValue (i, values [i], temp);
 ++
 ++                        if (is_new) { // new row
 ++                                if (editing || RowState == DataRowState.Detached)
 ++                                        Proposed = temp;
 ++                                else
 ++                                        Current = temp;
 ++                                return;
 ++                        }
 ++
 ++                        if (loadOption == LoadOption.OverwriteChanges 
 ++                            || (loadOption == LoadOption.PreserveChanges
 ++                                && rowState == DataRowState.Unchanged)) {
 ++                                Original = temp;
 ++                                if (editing)
 ++                                        Proposed = temp;
 ++                                else
 ++                                        Current = temp;
 ++                                rowState = DataRowState.Unchanged;
 ++                                action = DataRowAction.ChangeCurrentAndOriginal;
 ++                                return;
 ++                        }
 ++
 ++                        if (loadOption == LoadOption.PreserveChanges) {
 ++                                if (rowState != DataRowState.Deleted) {
 ++                                        Original = temp;
 ++                                        rowState = DataRowState.Modified;
 ++                                        action   = DataRowAction.ChangeOriginal;
 ++                                }
 ++                                return;
 ++                        }
 ++                                
 ++                        bool not_used = true;
 ++                        // Upsert
 ++                        if (rowState != DataRowState.Deleted) {
 ++                                int index = editing ? _proposed : _current;
 ++                                if (! RecordCache.CompareRecords (Table, index, temp)) {
 ++                                        if (editing)
 ++                                                Proposed = temp;
 ++                                        else
 ++                                                Current = temp;
 ++                                        not_used = false;
 ++                                        if (rowState == DataRowState.Unchanged)
 ++                                                rowState = DataRowState.Modified;
 ++                                }
 ++                        }
 ++                                
 ++                        if (not_used)
 ++                                Table.RecordCache.DisposeRecord (temp);
 ++                }
 ++#endif // NET_2_0
 +      }
-  
-       
-  
 + }
index 72737a8e2b63cc0d9e50366e4d091b8ca5ae2612,77da26feaecaab6a3bb8f39b87cb5ca9197f6812,d7bee298301bb9257f046d602c8db1e7dd3f3d01..a3cbb45804e42ff47a371aa07769f1472cb1c2ae
@@@@ -183,214 -183,54 -183,54 +187,54 @@@@ namespace System.Dat
                /// </summary>
                public DataRow Find (object key) 
                {
-                       return Find (key, // primary key value
-                                       true // ignore deleted records
-                                       );
-               }
-  
-                  /// <summary>
-                  ///     Searches records for the given primary key values.
-                  /// </summary>
-                  public DataRow Find (object [] keys)
-                  {
-                          return Find (keys, // primary key values
-                                       true  // ignore deleted records
-                                       );
-                  }
-                  
-                  /// <summary>
-                  ///     Searches records for the given primary key values populated into
-                  ///     a temporary cache index.
-                  /// </summary>
-                  internal DataRow Find (int index, int length)
-                  {
-                          return Find (index,     // record to find
-                                       length,    // length of primary key
-                                       true       // ignore deleted records
-                                       );
+                       return Find(new object[]{key});
 --             }
 ++                }
   
-                  /// <summary>
-                  ///     Searches records for the given single primary key.
-                  /// </summary>
-                  /// <param name='key'>Primary key value to be searched </param>
-                  /// <param name='ignoreDeleted'>
-                  ///    Ignore the records with row state DataRowState.Deleted
-                  ///    if true.
-                  /// </param>
-                  internal DataRow Find (object key, bool ignoreDeleted)
-                  {
-                          if (table.PrimaryKey.Length == 0)
+               /// <summary>
+               /// Gets the row containing the specified primary key values.
+               /// </summary>
 --             public DataRow Find (object[] keys) 
+++             public DataRow Find (object[] keys)
+               {
+                       if (table.PrimaryKey.Length == 0)
                                throw new MissingPrimaryKeyException ("Table doesn't have a primary key.");
-                       if (table.PrimaryKey.Length > 1)
-                               throw new ArgumentException ("Expecting " + table.PrimaryKey.Length +" value(s) for the key being indexed, but received 1 value(s).");
   
-                       if (key == null)
-  #if NET_1_1
-                               return null;
-  #else
-                               throw new ArgumentException("Expecting 1 value(s) for the key being indexed, but received 0 value(s).");
-  #endif
 --                      if (keys == null)
+++                     if (keys == null)
+                               throw new ArgumentException ("Expecting " + table.PrimaryKey.Length +" value(s) for the key being indexed, but received 0 value(s).");
+                                                                                                      
+                       Index index = table.GetIndex(table.PrimaryKey,null,DataViewRowState.None,null,false);
   
-                       DataColumn primaryKey = table.PrimaryKey[0];
-                       Index primaryKeyIndex = table.GetIndexByColumns(table.PrimaryKey);
-                       int tmpRecord = table.RecordCache.NewRecord();
-                       try {
-                               primaryKey.DataContainer[tmpRecord] = key;
-  
-                               // if we can search through index
-                               if (primaryKeyIndex != null) {
-                                       // get the child rows from the index
-                                       Node node = primaryKeyIndex.FindSimple(tmpRecord,1,true);
-                                       if (node != null) {
-                                               return node.Row;
-                                       }
-                               }
-                       
-                               //loop through all collection rows                      
-                               foreach (DataRow row in this) {
-                                       if (ignoreDeleted && row.RowState == DataRowState.Deleted)
-                                                  continue;
-                                          int index = row.IndexFromVersion(DataRowVersion.Default);
-                                          if (row.RowState == DataRowState.Deleted)
-                                                  index = row.Current;
-                                          if (primaryKey.DataContainer.CompareValues(index, tmpRecord) == 0) {
-                                                  return row;
-                                       }
-                               }
-                               return null;
-                       }
-                       finally {
-                               table.RecordCache.DisposeRecord(tmpRecord);
-                       }
-                  }
+                       int record = index.Find(keys);
+                       return (record != -1) ? table.RecordCache[record] : null;
+               }
   
-                  /// <summary>
-                  ///     Searches records for the given primary key values.
-                  /// </summary>
-                  /// <param name='keys'>Primary key values to be searched </param>
-                  /// <param name='ignoreDeleted'>
-                  ///    Ignore the records with row state DataRowState.Deleted
-                  ///    if true.
-                  /// </param>
-               internal DataRow Find (object[] keys, bool ignoreDeleted) 
+               internal DataRow Find(int index)
                {
-                          AssertFind (keys);
-  
                        DataColumn[] primaryKey = table.PrimaryKey;
-                       int tmpRecord = table.RecordCache.NewRecord();
-                       try {
-                               int numColumn = keys.Length;
-                               for (int i = 0; i < numColumn; i++) {
-                                       // according to MSDN: the DataType value for both columns must be identical.
-                                       primaryKey[i].DataContainer[tmpRecord] = keys[i];
+                       Index primaryKeyIndex = table.FindIndex(primaryKey);
+                       // if we can search through index
+                       if (primaryKeyIndex != null) {
+                               // get the child rows from the index
+                               int record = primaryKeyIndex.Find(index);
+                               if ( record != -1 ) {
+                                       return table.RecordCache[record];
                                }
-                               return Find(tmpRecord, numColumn, ignoreDeleted);
-                       }
-                       finally {
-                               table.RecordCache.DisposeRecord(tmpRecord);
-                       }
-               }
-  
-                  /// <summary>
-                  ///     Searches records for the given primary key values and the 
-                  ///     given version.
-                  /// </summary>
-                  /// <param name='keys'>Primary key values to be searched </param>
-                  /// <param name='version'>
-                  ///    Version of the rows to be searched for.
-                  /// </param>
-                  internal DataRow Find (object [] values, DataRowVersion version)
-                  {
-                          AssertFind (values);
-                                                                                                      
-                       DataColumn[] pk = table.PrimaryKey;
-                       int temp = table.RecordCache.NewRecord();
-                       try {
-                               for (int i = 0; i < pk.Length; i++)
-                                       pk [i].DataContainer[temp] = values [i];
-                               return Find(temp, version, false); // include deleted records also
-                       }
-                       finally {
-                               table.RecordCache.DisposeRecord(temp);
-                       }
-                  }
-  
-                  /// <summary>
-                  ///     Searches records for the given primary key values and the 
-                  ///     given version.
-                  /// </summary>
-                  /// <param name='record'>index of the record which holds the values to be searchd.
-                  /// </param>
-                  /// <param name='version'>
-                  ///    Version of the rows to be searched for.
-                  /// </param>
-                  /// <param name='ignoreDeleted'>Ignore the records with state Deleted </param>
-               private DataRow Find(int record, DataRowVersion version, bool ignoreDeleted)
-               {
-                          DataRow resultRow = null;
-                          if (version == DataRowVersion.Current) {
-                                  // index engine holds only the current records.
-                                  resultRow = IndexSearch (record);
-                                  if (resultRow != null)
-                                          return resultRow;
-                          }
-  
-                       // fallback : loop through all collection rows                  
-                          // if there is a matching record with state deleted, that won't be detected
-                          // in the above search. (deleted records are not part of index.
-                       foreach (DataRow row in this) {
-                               if (ignoreDeleted && row.RowState != DataRowState.Deleted) 
-                                          continue;
-                                  
-                                  int offset = row.IndexFromVersion(version);
-                                  if (offset < 0)
-                                          continue;
-                                  bool matching = true;
-                                  for (int i = 0; matching && i < table.PrimaryKey.Length; i++) { 
-                                          if (table.PrimaryKey [i].DataContainer.CompareValues(offset, record) != 0)
-                                                  matching = false;
-                                  }
-                                  if (matching) {
-                                          resultRow = row; 
-                                          break;
-                                  }
                        }
-                       return resultRow;
-  
-                  }
-  
-                  /// <summary>
-                  ///     Searches records for the given primary key values and the 
-                  ///     given version.
-                  /// </summary>
-                  /// <param name='index'> index of the record which holds the values to be searchd.
-                  /// </param>
-                  /// <param name='length'> length of primary keys </param>
-                  /// <param name='ignoreDeleted'> Ignore the records with state Deleted </param>
-               private DataRow Find(int index, int length, bool ignoreDeleted)
-               {
-                          DataRow resultRow = IndexSearch (index);
-                          if (resultRow != null)
-                                  return resultRow;
-                          
-                       //loop through all collection rows                      
-                       foreach (DataRow row in this) {
-                               if (ignoreDeleted && row.RowState != DataRowState.Deleted) 
-                                          continue;
-                                  
-                                  int rowIndex = row.IndexFromVersion(DataRowVersion.Default);
-                                  if (row.RowState == DataRowState.Deleted)
-                                          rowIndex = row.Current;
-                                  bool match = true;
-                                  for (int columnCnt = 0; columnCnt < length; ++columnCnt) { 
-                                          if (table.PrimaryKey[columnCnt].DataContainer.CompareValues(rowIndex, index) != 0) {
-                                                  match = false;
-                                          }
-                                  }
-                                  if ( match ) {
-                                          return row;
-                                  }
+                       else {
+                               //loop through all collection rows                      
+                               foreach (DataRow row in this) {
+                                       if (row.RowState != DataRowState.Deleted) {
+                                               int rowIndex = row.IndexFromVersion(DataRowVersion.Default);
+                                               bool match = true;
+                                               for (int columnCnt = 0; columnCnt < primaryKey.Length; ++columnCnt) { 
+                                                       if (primaryKey[columnCnt].DataContainer.CompareValues(rowIndex, index) != 0) {
+                                                               match = false;
+                                                       }
+                                               }
+                                               if ( match ) {
+                                                       return row;
+                                               }
+                                       }
+                               }
                        }
                        return null;
                }
                        //first check for null violations.
                        row._nullConstraintViolation = true;
                        row.CheckNullConstraints();
-                       // This validates constraints in the specific order : 
-                       // first unique/primary keys first, then Foreignkeys, etc
-                       ArrayList uniqueConstraintsDone = new ArrayList();
-                       ArrayList foreignKeyConstraintsDone = new ArrayList();
-                       try {
-                               foreach(Constraint constraint in table.Constraints.UniqueConstraints) {
-                                       constraint.AssertConstraint(row);
-                                       uniqueConstraintsDone.Add(constraint);
-                               }
-                       
-                               foreach(Constraint constraint in table.Constraints.ForeignKeyConstraints) {
-                                       constraint.AssertConstraint(row);
-                                       foreignKeyConstraintsDone.Add(constraint);
-                               }
-                       }
-                       // if one of the AssertConstraint failed - we need to "rollback" all the changes
-                       // caused by AssertCoinstraint calls already succeeded
-                       catch(ConstraintException e) {
-                               RollbackAsserts(row,foreignKeyConstraintsDone,uniqueConstraintsDone);
-                               throw e;
-                       }
-                       catch(InvalidConstraintException e) {   
-                               RollbackAsserts(row,foreignKeyConstraintsDone,uniqueConstraintsDone);
-                               throw e;
-                       }
-               }
   
-               private void RollbackAsserts(DataRow row,ICollection foreignKeyConstraintsDone,
-                       ICollection uniqueConstraintsDone)
-               {
-                       // if any of constraints assert failed - 
-                       // we have to rollback all the asserts scceeded
-                       // on order reverse to thier original execution
-                       foreach(Constraint constraint in foreignKeyConstraintsDone) {
-                               constraint.RollbackAssert(row);
+                       int newRecord = (row.Proposed >= 0) ? row.Proposed : row.Current;
++                      if (newRecord < 0)
++                              return;
++ 
+                       foreach(Index index in table.Indexes) {
+                               index.Update(row,newRecord);
                        }
   
-                       foreach(Constraint constraint in uniqueConstraintsDone) {
-                               constraint.RollbackAssert(row);
+                       foreach(Constraint constraint in table.Constraints) {
+                               try {
+                                       constraint.AssertConstraint(row);
+                               }
+                               catch(Exception e) {
+                                       // remove row from indexes
+                                       foreach(Index index in table.Indexes) {
+                                               index.Delete(newRecord);
+                                       }
+                                       throw e;
+                               }
                        }
                }
        }
index da7d68cea220c8a2e9f9311de19b919c7732d93d,c4563dfbb4bb07146797988576384b76bb8091c0,4d9182ed8240a804dbe6d62fd118a5102a608e25..05bf1e9eda3b0e9e501fca09363f5890157776af
-  //
-  // System.Data.DataTable.cs
-  //
-  // Author:
-  //   Franklin Wise <gracenote@earthlink.net>
-  //   Christopher Podurgiel (cpodurgiel@msn.com)
-  //   Daniel Morgan <danmorg@sc.rr.com>
-  //   Rodrigo Moya <rodrigo@ximian.com>
-  //   Tim Coleman (tim@timcoleman.com)
-  //   Ville Palo <vi64pa@koti.soon.fi>
-  //   Sureshkumar T <tsureshkumar@novell.com>
-  //
-  // (C) Chris Podurgiel
-  // (C) Ximian, Inc 2002
-  // Copyright (C) Tim Coleman, 2002-2003
-  // Copyright (C) Daniel Morgan, 2002-2003
-  //
-  
-  //
-  // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-  //
-  // Permission is hereby granted, free of charge, to any person obtaining
-  // a copy of this software and associated documentation files (the
-  // "Software"), to deal in the Software without restriction, including
-  // without limitation the rights to use, copy, modify, merge, publish,
-  // distribute, sublicense, and/or sell copies of the Software, and to
-  // permit persons to whom the Software is furnished to do so, subject to
-  // the following conditions:
-  // 
-  // The above copyright notice and this permission notice shall be
-  // included in all copies or substantial portions of the Software.
-  // 
-  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-  //
-  
-  using System;
-  using System.Data.Common;
-  using System.Collections;
-  using System.ComponentModel;
-  using System.Globalization;
-  using System.IO;
-  using System.Runtime.Serialization;
-  using System.Xml;
-  using System.Xml.Schema;
-  using Mono.Data.SqlExpressions;
-  
-  namespace System.Data {
-       //[Designer]
-       [ToolboxItem (false)]
-       [DefaultEvent ("RowChanging")]
-       [DefaultProperty ("TableName")]
-       [DesignTimeVisible (false)]
-       [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DataTableEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
-       [Serializable]
-       public class DataTable : MarshalByValueComponent, IListSource, ISupportInitialize, ISerializable 
-       {
-               #region Fields
-  
-               internal DataSet dataSet;   
-               
-               private bool _caseSensitive;
-               private DataColumnCollection _columnCollection;
-               private ConstraintCollection _constraintCollection;
-               // never access it. Use DefaultView.
-               private DataView _defaultView;
-  
-               private string _displayExpression;
-               private PropertyCollection _extendedProperties;
-               private bool _hasErrors;
-               private CultureInfo _locale;
-               private int _minimumCapacity;
-               private string _nameSpace;
-               private DataRelationCollection _childRelations; 
-               private DataRelationCollection _parentRelations;
-               private string _prefix;
-               private DataColumn[] _primaryKey;
-               private DataRowCollection _rows;
-               private ISite _site;
-               private string _tableName;
-               private bool _containsListCollection;
-               private string _encodedTableName;
-               internal bool _duringDataLoad;
-               internal bool _nullConstraintViolationDuringDataLoad;
-               private bool dataSetPrevEnforceConstraints;
-               private bool dataTablePrevEnforceConstraints;
-               private bool enforceConstraints = true;
-               private DataRowBuilder _rowBuilder;
-               private ArrayList _indexes;
-               private RecordCache _recordCache;
-               private int _defaultValuesRowIndex = -1;
-               protected internal bool fInitInProgress;
-  
-               // If CaseSensitive property is changed once it does not anymore follow owner DataSet's 
-               // CaseSensitive property. So when you lost you virginity it's gone for ever
-               private bool _virginCaseSensitive = true;
-               
-               #endregion //Fields
-               
-               private delegate void PostEndInit();
-  
-               /// <summary>
-               /// Initializes a new instance of the DataTable class with no arguments.
-               /// </summary>
-               public DataTable () 
-               {
-                       dataSet = null;
-                       _columnCollection = new DataColumnCollection(this);
-                       _constraintCollection = new ConstraintCollection(this); 
-                       _extendedProperties = new PropertyCollection();
-                       _tableName = "";
-                       _nameSpace = null;
-                       _caseSensitive = false;         //default value
-                       _displayExpression = null;
-                       _primaryKey = null;
-                       _site = null;
-                       _rows = new DataRowCollection (this);
-                       _indexes = new ArrayList();
-                       _recordCache = new RecordCache(this);
-                       
-                       //LAMESPEC: spec says 25 impl does 50
-                       _minimumCapacity = 50;
-                       
-                       _childRelations = new DataRelationCollection.DataTableRelationCollection (this);
-                       _parentRelations = new DataRelationCollection.DataTableRelationCollection (this);
-               }
-  
-               /// <summary>
-               /// Intitalizes a new instance of the DataTable class with the specified table name.
-               /// </summary>
-               public DataTable (string tableName) : this () 
-               {
-                       _tableName = tableName;
-               }
-  
-               /// <summary>
-               /// Initializes a new instance of the DataTable class with the SerializationInfo and the StreamingContext.
-               /// </summary>
-               [MonoTODO]
-               protected DataTable (SerializationInfo info, StreamingContext context)
-                       : this () 
-               {
-                       string schema = info.GetString ("XmlSchema");
-                       string data = info.GetString ("XmlDiffGram");
-                       
-                       DataSet ds = new DataSet ();
-                       ds.ReadXmlSchema (new StringReader (schema));
-                       ds.Tables [0].CopyProperties (this);
-                       ds = new DataSet ();
-                       ds.Tables.Add (this);
-                       ds.ReadXml (new StringReader (data), XmlReadMode.DiffGram);
-                       ds.Tables.Remove (this);
-  /* keeping for a while. With the change above, we shouldn't have to consider 
-   * DataTable mode in schema inference/read.
-                       XmlSchemaMapper mapper = new XmlSchemaMapper (this);
-                       XmlTextReader xtr = new XmlTextReader(new StringReader (schema));
-                       mapper.Read (xtr);
-                       
-                       XmlDiffLoader loader = new XmlDiffLoader (this);
-                       xtr = new XmlTextReader(new StringReader (data));
-                       loader.Load (xtr);
-  */
-               }
-  
-  #if NET_2_0
-               public DataTable (string tableName, string tbNamespace)
-                       : this (tableName)
-               {
-                       _nameSpace = tbNamespace;
-               }
-  #endif
-  
-               /// <summary>
-               /// Indicates whether string comparisons within the table are case-sensitive.
-               /// </summary>
-               [DataSysDescription ("Indicates whether comparing strings within the table is case sensitive.")]        
-               public bool CaseSensitive {
-                       get { 
-                               if (_virginCaseSensitive && dataSet != null)
-                                       return dataSet.CaseSensitive; 
-                               else
-                                       return _caseSensitive;
-                               }
-                       set {
-                               if (_childRelations.Count > 0 || _parentRelations.Count > 0) {
-                                       throw new ArgumentException ("Cannot change CaseSensitive or Locale property. This change would lead to at least one DataRelation or Constraint to have different Locale or CaseSensitive settings between its related tables.");
-                               }
-                               _virginCaseSensitive = false;
-                               _caseSensitive = value; 
-                       }
-               }
-  
-               internal void ChangedDataColumn (DataRow dr, DataColumn dc, object pv) 
-               {
-                       DataColumnChangeEventArgs e = new DataColumnChangeEventArgs (dr, dc, pv);
-                       OnColumnChanged(e);
-               }
-  
-               internal void ChangingDataColumn (DataRow dr, DataColumn dc, object pv) 
-               {
-                       DataColumnChangeEventArgs e = new DataColumnChangeEventArgs (dr, dc, pv);
-                       OnColumnChanging (e);
-               }
-  
-               internal void DeletedDataRow (DataRow dr, DataRowAction action) 
-               {
-                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);
-                       OnRowDeleted (e);
-               }
-  
-               internal void DeletingDataRow (DataRow dr, DataRowAction action) 
-               {
-                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);
-                       OnRowDeleting(e);
-               }
-  
-               internal void ChangedDataRow (DataRow dr, DataRowAction action) 
-               {
-                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);
-                       OnRowChanged (e);
-               }
-  
-               internal void ChangingDataRow (DataRow dr, DataRowAction action) 
-               {
-                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);
-                       OnRowChanging (e);
-               }
-  
-               /// <summary>
-               /// Gets the collection of child relations for this DataTable.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Returns the child relations for this table.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public DataRelationCollection ChildRelations {
-                       get {
-                               return _childRelations;
-                       }
-               }
-  
-               /// <summary>
-               /// Gets the collection of columns that belong to this table.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("The collection that holds the columns for this table.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public DataColumnCollection Columns {
-                       get { return _columnCollection; }
-               }
-  
-               /// <summary>
-               /// Gets the collection of constraints maintained by this table.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("The collection that holds the constraints for this table.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public ConstraintCollection Constraints {
-                       get { return _constraintCollection; }
-               }
-  
-               /// <summary>
-               /// Gets the DataSet that this table belongs to.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Indicates the DataSet to which this table belongs.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public DataSet DataSet {
-                       get { return dataSet; }
-               }
-  
-               
-  
-               /// <summary>
-               /// Gets a customized view of the table which may 
-               /// include a filtered view, or a cursor position.
-               /// </summary>
-               [MonoTODO]      
-               [Browsable (false)]
-               [DataSysDescription ("This is the default DataView for the table.")]
-               public DataView DefaultView {
-                       get {
-                               if (_defaultView == null)
-                                       _defaultView = new DataView (this);
-                               return _defaultView;
-                       }
-               }
-               
-  
-               /// <summary>
-               /// Gets or sets the expression that will return 
-               /// a value used to represent this table in the user interface.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("The expression used to compute the data-bound value of this row.")]       
-               [DefaultValue ("")]
-               public string DisplayExpression {
-                       get { return _displayExpression == null ? "" : _displayExpression; }
-                       set { _displayExpression = value; }
-               }
-  
-               /// <summary>
-               /// Gets the collection of customized user information.
-               /// </summary>
-               [Browsable (false)]
-               [DataCategory ("Data")]
-               [DataSysDescription ("The collection that holds custom user information.")]
-               public PropertyCollection ExtendedProperties {
-                       get { return _extendedProperties; }
-               }
-  
-               /// <summary>
-               /// Gets a value indicating whether there are errors in 
-               /// any of the_rows in any of the tables of the DataSet to 
-               /// which the table belongs.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Returns whether the table has errors.")]
-               public bool HasErrors {
-                       get { 
-                               // we can not use the _hasError flag because we do not know when to turn it off!
-                               for (int i = 0; i < _rows.Count; i++)
-                               {
-                                       if (_rows[i].HasErrors)
-                                               return true;
-                               }
-                               return false;
-                       }
-               }
-  
-               /// <summary>
-               /// Gets or sets the locale information used to 
-               /// compare strings within the table.
-               /// </summary>
-               [DataSysDescription ("Indicates a locale under which to compare strings within the table.")]
-               public CultureInfo Locale {
-                       get { 
-                               // if the locale is null, we check for the DataSet locale
-                               // and if the DataSet is null we return the current culture.
-                               // this way if DataSet locale is changed, only if there is no locale for 
-                               // the DataTable it influece the Locale get;
-                               if (_locale != null)
-                                       return _locale;
-                               if (DataSet != null)
-                                       return DataSet.Locale;
-                               return CultureInfo.CurrentCulture;
-                       }
-                       set { 
-                               if (_childRelations.Count > 0 || _parentRelations.Count > 0) {
-                                       throw new ArgumentException ("Cannot change CaseSensitive or Locale property. This change would lead to at least one DataRelation or Constraint to have different Locale or CaseSensitive settings between its related tables.");
-                               }
-                               if (_locale == null || !_locale.Equals(value))
-                                       _locale = value; 
-                       }
-               }
-  
-               /// <summary>
-               /// Gets or sets the initial starting size for this table.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates an initial starting size for this table.")]
-               [DefaultValue (50)]
-               public int MinimumCapacity {
-                       get { return _minimumCapacity; }
-                       set { _minimumCapacity = value; }
-               }
-  
-               /// <summary>
-               /// Gets or sets the namespace for the XML represenation 
-               /// of the data stored in the DataTable.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the XML uri namespace for the elements contained in this table.")]
-               public string Namespace {
-                       get {
-                               if (_nameSpace != null)
-                                       return _nameSpace;
-                               else if (dataSet != null)
-                                       return dataSet.Namespace;
-                               return String.Empty;
-                       }
-                       set { _nameSpace = value; }
-               }
-  
-               /// <summary>
-               /// Gets the collection of parent relations for 
-               /// this DataTable.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Returns the parent relations for this table.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public DataRelationCollection ParentRelations {
-                       get {   
-                               return _parentRelations;
-                       }
-               }
-  
-               /// <summary>
-               /// Gets or sets the namespace for the XML represenation
-               ///  of the data stored in the DataTable.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the Prefix of the namespace used for this table in XML representation.")]
-               [DefaultValue ("")]
-               public string Prefix {
-                       get { return _prefix == null ? "" : _prefix; }
-                       set {
-                               // Prefix cannot contain any special characters other than '_' and ':'
-                               for (int i = 0; i < value.Length; i++) {
-                                       if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))
-                                               throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");
-                               }
-                               _prefix = value;
-                       }
-               }
-  
-               /// <summary>
-               /// Gets or sets an array of columns that function as 
-               /// primary keys for the data table.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the column(s) that represent the primary key for this table.")]
-               [EditorAttribute ("Microsoft.VSDesigner.Data.Design.PrimaryKeyEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
-               [TypeConverterAttribute ("System.Data.PrimaryKeyTypeConverter, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-               public DataColumn[] PrimaryKey {
-                       get {
-                               UniqueConstraint uc = UniqueConstraint.GetPrimaryKeyConstraint( Constraints);
-                               if (null == uc) return new DataColumn[] {};
-                               return uc.Columns;
-                       }
-                       set {
-                               UniqueConstraint oldPKConstraint = UniqueConstraint.GetPrimaryKeyConstraint( Constraints);
-                               
-                               // first check if value is the same as current PK.
-                               if (oldPKConstraint != null && DataColumn.AreColumnSetsTheSame(value, oldPKConstraint.Columns))
-                                       return;
-  
-                               // remove PK Constraint
-                               if(oldPKConstraint != null) {
-                                       Constraints.Remove(oldPKConstraint);
-                               }
-                               
-                               if (value != null) {
-                                       //Does constraint exist for these columns
-                                       UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet(
-                                               this.Constraints, (DataColumn[]) value);
-                               
-                                       //if constraint doesn't exist for columns
-                                       //create new unique primary key constraint
-                                       if (null == uc) {
-                                               foreach (DataColumn Col in (DataColumn[]) value) {
-  
-                                                       if (Col.Table == null)
-                                                               break;
-  
-                                                       if (Columns.IndexOf (Col) < 0)
-                                                               throw new ArgumentException ("PrimaryKey columns do not belong to this table.");
-                                               }
-  
-  
-                                               uc = new UniqueConstraint( (DataColumn[]) value, true);
-                                       
-                                               Constraints.Add (uc);
-                                       }
-                                       else { 
-                                               //set existing constraint as the new primary key
-                                               UniqueConstraint.SetAsPrimaryKey(this.Constraints, uc);
-                                       }
-  
-                                       // if we really supplied some columns fo primary key - 
-                                       // rebuild indexes fo all foreign key constraints
-                                       if(value.Length > 0) {
-                                               foreach(ForeignKeyConstraint constraint in this.Constraints.ForeignKeyConstraints){
-                                                       try {
-                                                               constraint.AssertConstraint();
-                                                       } catch (ConstraintException ex) {
-                                                               throw new ArgumentException (ex.Message, ex);
-                                                       }
-                                               }
-                                       }
-                               }
-                               else {
-                                       // if primary key is null now - drop all the indexes for foreign key constraints
-                                       foreach(ForeignKeyConstraint constraint in this.Constraints.ForeignKeyConstraints){
-                                               Index index = constraint.Index;
-                                               constraint.Index = null;
-                                               this.DropIndex(index);
-                                       }
-                               }
-                               
-                       }
-               }
-  
-               /// <summary>
-               /// Gets the collection of_rows that belong to this table.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Indicates the collection that holds the rows of data for this table.")]   
-               public DataRowCollection Rows {
-                       get { return _rows; }
-               }
-  
-               /// <summary>
-               /// Gets or sets an System.ComponentModel.ISite 
-               /// for the DataTable.
-               /// </summary>
-               [Browsable (false)]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public override ISite Site {
-                       get { return _site; }
-                       set { _site = value; }
-               }
-  
-               /// <summary>
-               /// Gets or sets the name of the the DataTable.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the name used to look up this table in the Tables collection of a DataSet.")]
-               [DefaultValue ("")]     
-               [RefreshProperties (RefreshProperties.All)]
-               public string TableName {
-                       get { return _tableName == null ? "" : _tableName; }
-                       set { _tableName = value; }
-               }
-               
-               bool IListSource.ContainsListCollection {
-                       get {
-                               // the collection is a DataView
-                               return false;
-                       }
-               }
-               
-               internal RecordCache RecordCache {
-                       get {
-                               return _recordCache;
-                       }
-               }
-               
-               private bool EnforceConstraints {
-                       get { return enforceConstraints; }
-                       set {
-                               if (value != enforceConstraints) {
-                                       if (value) {
-                                               // first assert all unique constraints
-                                               foreach (UniqueConstraint uc in this.Constraints.UniqueConstraints)
-                                               uc.AssertConstraint ();
-                                               // then assert all foreign keys
-                                               foreach (ForeignKeyConstraint fk in this.Constraints.ForeignKeyConstraints)
-                                                       fk.AssertConstraint ();
-                                       }
-                                       enforceConstraints = value;
-                               }
-                       }
-               }
-  
-               internal bool RowsExist(DataColumn[] columns, DataColumn[] relatedColumns,DataRow row)
-               {
-                       int curIndex = row.IndexFromVersion(DataRowVersion.Default);
-                       int tmpRecord = RecordCache.NewRecord();
-  
-                       try {
-                               for (int i = 0; i < relatedColumns.Length; i++) {
-                                       // according to MSDN: the DataType value for both columns must be identical.
-                                       columns[i].DataContainer.CopyValue(relatedColumns[i].DataContainer, curIndex, tmpRecord);
-                               }
-  
-                               return RowsExist(columns, tmpRecord, relatedColumns.Length);
-                       }
-                       finally {
-                               RecordCache.DisposeRecord(tmpRecord);
-                       }
-               }
-  
-               bool RowsExist(DataColumn[] columns, int index, int length)
-               {
-                       bool rowsExist = false;
-                       Index indx = this.GetIndexByColumns (columns);
-  
-                       if (indx != null) { // lookup for a row in index                        
-                               rowsExist = (indx.FindSimple (index, length, false) != null);
-                       } 
-                       
-                       if(indx == null || rowsExist == false) { 
-                               // no index or rowExist= false, we have to perform full-table scan
-                               // check that there is a parent for this row.
-                               foreach (DataRow thisRow in this.Rows) {
-                                       if (thisRow.RowState != DataRowState.Deleted) {
-                                               bool match = true;
-                                               // check if the values in the columns are equal
-                                               int thisIndex = thisRow.IndexFromVersion(DataRowVersion.Current);
-                                               foreach (DataColumn column in columns) {
-                                                       if (column.DataContainer.CompareValues(thisIndex, index) != 0) {
-                                                               match = false;
-                                                               break;
-                                                       }       
-                                               }
-                                               if (match) {// there is a row with columns values equals to those supplied.
-                                                       rowsExist = true;
-                                                       break;
-                                               }
-                                       }
-                               }                               
-                       }
-                       return rowsExist;
-               }
-  
-               /// <summary>
-               /// Commits all the changes made to this table since the 
-               /// last time AcceptChanges was called.
-               /// </summary>
-               public void AcceptChanges () 
-               {
-                       //FIXME: Do we need to validate anything here or
-                       //try to catch any errors to deal with them?
-                       
-                       // we do not use foreach because if one of the rows is in Delete state
-                       // it will be romeved from Rows and we get an exception.
-                       DataRow myRow;
-                       for (int i = 0; i < Rows.Count; )
-                       {
-                               myRow = Rows[i];
-                               myRow.AcceptChanges();
-  
-                               // if the row state is Detached it meens that it was removed from row list (Rows)
-                               // so we should not increase 'i'.
-                               if (myRow.RowState != DataRowState.Detached)
-                                       i++;
-                       }
-               }
-  
-               /// <summary>
-               /// Begins the initialization of a DataTable that is used 
-               /// on a form or used by another component. The initialization
-               /// occurs at runtime.
-               /// </summary>
-               public virtual void BeginInit () 
-               {
-                       fInitInProgress = true;
-               }
-  
-               /// <summary>
-               /// Turns off notifications, index maintenance, and 
-               /// constraints while loading data.
-               /// </summary>
-               [MonoTODO]
-               public void BeginLoadData () 
-               {
-                       if (!this._duringDataLoad)
-                       {
-                               //duringDataLoad is important to EndLoadData and
-                               //for not throwing unexpected exceptions.
-                               this._duringDataLoad = true;
-                               this._nullConstraintViolationDuringDataLoad = false;
-                       
-                               if (this.dataSet != null)
-                               {
-                                       //Saving old Enforce constraints state for later
-                                       //use in the EndLoadData.
-                                       this.dataSetPrevEnforceConstraints = this.dataSet.EnforceConstraints;
-                                       this.dataSet.EnforceConstraints = false;
-                               }
-                               else {
-                                       //if table does not belong to any data set use EnforceConstraints of the table
-                                       this.dataTablePrevEnforceConstraints = this.EnforceConstraints;
-                                       this.EnforceConstraints = false;
-                               }
-                       }
-                       return;
-               }
-  
-               /// <summary>
-               /// Clears the DataTable of all data.
-               /// </summary>
-               public void Clear () {
-                          // Foriegn key constraints are checked in _rows.Clear method
-                       _rows.Clear ();
-  #if NET_2_0
-                          OnTableCleared (new DataTableClearEventArgs (this));
-  #endif // NET_2_0
-  
-               }
-  
-               /// <summary>
-               /// Clones the structure of the DataTable, including
-               ///  all DataTable schemas and constraints.
-               /// </summary>
-               public virtual DataTable Clone () 
-               {
-                        // Use Activator so we can use non-public constructors.
-                       DataTable Copy = (DataTable) Activator.CreateInstance(GetType(), true);                 
-                       CopyProperties (Copy);
-                       return Copy;
-               }
-  
-               /// <summary>
-               /// Computes the given expression on the current_rows that 
-               /// pass the filter criteria.
-               /// </summary>
-               [MonoTODO]
-               public object Compute (string expression, string filter) 
-               {
-                       // expression is an aggregate function
-                       // filter is an expression used to limit rows
-  
-                       DataRow[] rows = Select(filter);
-                       
-                       Parser parser = new Parser (rows);
-                       IExpression expr = parser.Compile (expression);
-                       object obj = expr.Eval (rows[0]);
-                       
-                       return obj;
-               }
-  
-               /// <summary>
-               /// Copies both the structure and data for this DataTable.
-               /// </summary>
-               public DataTable Copy () 
-               {
-                       DataTable copy = Clone();
-  
-                       copy._duringDataLoad = true;
-                       foreach (DataRow row in Rows) {
-                               DataRow newRow = copy.NewNotInitializedRow();
-                               copy.Rows.Add(newRow);
-                               CopyRow(row,newRow);
-                       }
-                       copy._duringDataLoad = false;           
-                       return copy;
-               }
-  
-               internal void CopyRow(DataRow fromRow,DataRow toRow)
-               {
-                       fromRow.CopyState(toRow);
-  
-                       if (fromRow.HasVersion(DataRowVersion.Original)) {
-                               toRow._original = toRow.Table.RecordCache.CopyRecord(this,fromRow._original,-1);
-                       }
-  
-                       if (fromRow.HasVersion(DataRowVersion.Current)) {
-                               toRow._current = toRow.Table.RecordCache.CopyRecord(this,fromRow._current,-1);
-                       }
-               }
-  
-               private void CopyProperties (DataTable Copy) 
-               {
-                                       
-                       Copy.CaseSensitive = CaseSensitive;
-                       Copy._virginCaseSensitive = _virginCaseSensitive;
-  
-                       // Copy.ChildRelations
-                       // Copy.Constraints
-                       // Copy.Container
-                       // Copy.DefaultView
-                       // Copy.DesignMode
-                       Copy.DisplayExpression = DisplayExpression;
-                       if(ExtendedProperties.Count > 0) {
-                               //  Cannot copy extended properties directly as the property does not have a set accessor
-                               Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);
-                               ExtendedProperties.Keys.CopyTo (tgtArray, 0);
-                               for (int i=0; i < ExtendedProperties.Count; i++)
-                                       Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);
-                       }
-                       Copy.Locale = Locale;
-                       Copy.MinimumCapacity = MinimumCapacity;
-                       Copy.Namespace = Namespace;
-                       // Copy.ParentRelations
-                       Copy.Prefix = Prefix;
-                       Copy.Site = Site;
-                       Copy.TableName = TableName;
-  
-  
-  
-                       // Copy columns
-                       foreach (DataColumn Column in Columns) {
-                               // When cloning a table, the columns may be added in the default
-                               // constructor.
-                               if (!Copy.Columns.Contains(Column.ColumnName))                                                          Copy.Columns.Add (CopyColumn (Column)); 
-                       }
-  
-                       CopyConstraints(Copy);
-                       // add primary key to the copy
-                       if (PrimaryKey.Length > 0)
-                       {
-                               DataColumn[] pColumns = new DataColumn[PrimaryKey.Length];
-                               for (int i = 0; i < pColumns.Length; i++)
-                                       pColumns[i] = Copy.Columns[PrimaryKey[i].ColumnName];
-  
-                               Copy.PrimaryKey = pColumns;
-                       }
-               }
-  
-               private void CopyConstraints(DataTable copy)
-               {
-                       UniqueConstraint origUc;
-                       UniqueConstraint copyUc;
-                       for (int i = 0; i < this.Constraints.Count; i++)
-                       {
-                               if (this.Constraints[i] is UniqueConstraint)
-                               {
-                                       origUc = (UniqueConstraint)this.Constraints[i];
-                                       DataColumn[] columns = new DataColumn[origUc.Columns.Length];
-                                       for (int j = 0; j < columns.Length; j++)
-                                               columns[j] = copy.Columns[origUc.Columns[j].ColumnName];
-                                       
-                                       copyUc = new UniqueConstraint(origUc.ConstraintName, columns, origUc.IsPrimaryKey);
-                                       copy.Constraints.Add(copyUc);
-                               }
-                       }
-               }
-               /// <summary>
-               /// Ends the initialization of a DataTable that is used 
-               /// on a form or used by another component. The 
-               /// initialization occurs at runtime.
-               /// </summary>
-               [MonoTODO]
-               public virtual void EndInit () 
-               {
-                       fInitInProgress = false;
-                       // Add the constraints
-                       PostEndInit _postEndInit = new PostEndInit (_constraintCollection.PostEndInit);
-                       _postEndInit();
-               }
-  
-               /// <summary>
-               /// Turns on notifications, index maintenance, and 
-               /// constraints after loading data.
-               /// </summary>
-               public void EndLoadData() 
-               {
-                       int i = 0;
-                       if (this._duringDataLoad) 
-                       {
-                               
-                               if (this.dataSet !=null)
-                               {
-                                       //Getting back to previous EnforceConstraint state
-                                       this.dataSet.EnforceConstraints = this.dataSetPrevEnforceConstraints;
-                               }
-                               else {
-                                       //Getting back to the table's previous EnforceConstraint state
-                                       this.EnforceConstraints = this.dataTablePrevEnforceConstraints;
-                               }
-  
-                               if(this._nullConstraintViolationDuringDataLoad) {
-                                       this._nullConstraintViolationDuringDataLoad = false;
-                                       throw new ConstraintException ("Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.");
-                               }
-  
-                               //Returning from loading mode, raising exceptions as usual
-                               this._duringDataLoad = false;
-  
-                       }
-  
-               }
-  
-               /// <summary>
-               /// Gets a copy of the DataTable that contains all
-               ///  changes made to it since it was loaded or 
-               ///  AcceptChanges was last called.
-               /// </summary>
-               public DataTable GetChanges() 
-               {
-                       return GetChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
-               }
-  
-               /// <summary>
-               /// Gets a copy of the DataTable containing all 
-               /// changes made to it since it was last loaded, or 
-               /// since AcceptChanges was called, filtered by DataRowState.
-               /// </summary>
-               public DataTable GetChanges(DataRowState rowStates) 
-               {
-                       DataTable copyTable = null;
-  
-                       IEnumerator rowEnumerator = Rows.GetEnumerator();
-                       while (rowEnumerator.MoveNext()) {
-                               DataRow row = (DataRow)rowEnumerator.Current;
-                               // The spec says relationship constraints may cause Unchanged parent rows to be included but
-                               // MS .NET 1.1 does not include Unchanged rows even if their child rows are changed.
-                               if (row.IsRowChanged(rowStates)) {
-                                       if (copyTable == null)
-                                               copyTable = Clone();
-                                       DataRow newRow = copyTable.NewRow();
-                                       row.CopyValuesToRow(newRow);
-                                       copyTable.Rows.Add (newRow);
-                               }
-                       }
-                        
-                       return copyTable;
-               }
-  
-  #if NET_2_0
-               [MonoTODO]
-               public DataTableReader GetDataReader ()
-               {
-                       throw new NotImplementedException ();
-               }
-  #endif
-  
-               /// <summary>
-               /// Gets an array of DataRow objects that contain errors.
-               /// </summary>
-               public DataRow[] GetErrors () 
-               {
-                       ArrayList errors = new ArrayList();
-                       for (int i = 0; i < _rows.Count; i++)
-                       {
-                               if (_rows[i].HasErrors)
-                                       errors.Add(_rows[i]);
-                       }
-                       
-                       return (DataRow[]) errors.ToArray(typeof(DataRow));
-               }
-       
-               /// <summary>
-               /// This member is only meant to support Mono's infrastructure 
-               /// </summary>
-               protected virtual DataTable CreateInstance () 
-               {
-                       return Activator.CreateInstance (this.GetType (), true) as DataTable;
-               }
-  
-               /// <summary>
-               /// This member is only meant to support Mono's infrastructure 
-               /// </summary>
-               protected virtual Type GetRowType () 
-               {
-                       return typeof (DataRow);
-               }
-  
-               /// <summary>
-               /// This member is only meant to support Mono's infrastructure 
-               /// 
-               /// Used for Data Binding between System.Web.UI. controls 
-               /// like a DataGrid
-               /// or
-               /// System.Windows.Forms controls like a DataGrid
-               /// </summary>
-               IList IListSource.GetList () 
-               {
-                       IList list = (IList) DefaultView;
-                       return list;
-               }
-                               
-               /// <summary>
-               /// Copies a DataRow into a DataTable, preserving any 
-               /// property settings, as well as original and current values.
-               /// </summary>
-               public void ImportRow (DataRow row) 
-               {
-                       DataRow newRow = NewRow();
-                       row.CopyValuesToRow (newRow);
-                          if (row.RowState != DataRowState.Detached)
-                                  Rows.Add (newRow);
-                       row.CopyState (newRow);
-               }
-  
-               internal int DefaultValuesRowIndex
-               {
-                       get {
-                               return _defaultValuesRowIndex;
-                       }       
-               }
-  
-               /// <summary>
-               /// This member is only meant to support Mono's infrastructure          
-               /// </summary>
-               void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) 
-               {
-                       DataSet dset;
-                       if (dataSet != null)
-                               dset = dataSet;
-                       else {
-                               dset = new DataSet ("tmpDataSet");
-                               dset.Tables.Add (this);
-                       }
-                       
-                       StringWriter sw = new StringWriter ();
-                       XmlTextWriter tw = new XmlTextWriter (sw);
-                       tw.Formatting = Formatting.Indented;
-                       dset.WriteIndividualTableContent (tw, this, XmlWriteMode.DiffGram);
-                       tw.Close ();
-                       
-                       StringWriter sw2 = new StringWriter ();
-                       DataTableCollection tables = new DataTableCollection (dset);
-                       tables.Add (this);
-                       XmlSchemaWriter.WriteXmlSchema (dset, new XmlTextWriter (sw2), tables, null);
-                       sw2.Close ();
-                       
-                       info.AddValue ("XmlSchema", sw2.ToString(), typeof(string));
-                       info.AddValue ("XmlDiffGram", sw.ToString(), typeof(string));
-               }
-  
-  #if NET_2_0
-                  /// <summary>
-                  ///     Loads the table with the values from the reader
-                  /// </summary>
-               public void Load (IDataReader reader)
-               {
-                          Load (reader, LoadOption.PreserveChanges);
-               }
-  
-                  /// <summary>
-                  ///     Loads the table with the values from the reader and the pattern
-                  ///     of the changes to the existing rows or the new rows are based on
-                  ///     the LoadOption passed.
-                  /// </summary>
-               public void Load (IDataReader reader, LoadOption loadOption)
-               {
-                          bool prevEnforceConstr = this.EnforceConstraints;
-                          try {
-                                  this.EnforceConstraints = false;
-                                  int [] mapping = DbDataAdapter.BuildSchema (reader, this, SchemaType.Mapped, 
-                                                                              MissingSchemaAction.AddWithKey,
-                                                                              MissingMappingAction.Passthrough, 
-                                                                              new DataTableMappingCollection ());
-                                  DbDataAdapter.FillFromReader (this,
-                                                                reader,
-                                                                0, // start from
-                                                                0, // all records
-                                                                mapping,
-                                                                loadOption);
-                          } finally {
-                                  this.EnforceConstraints = prevEnforceConstr;
-                          }
-               }
-  
-                  
-  #endif
-  
-               /// <summary>
-               /// Finds and updates a specific row. If no matching row
-               ///  is found, a new row is created using the given values.
-               /// </summary>
-               public DataRow LoadDataRow (object[] values, bool fAcceptChanges) 
-               {
-                       DataRow row = null;
-                       if (PrimaryKey.Length == 0) {
-                               row = Rows.Add (values);
-                               if (fAcceptChanges)
-                                       row.AcceptChanges ();
-                       }
-                       else {
-                               bool hasPrimaryValues = true;
-                               // initiate an array that has the values of the primary keys.
-                               object[] keyValues = new object[PrimaryKey.Length];
-                               for (int i = 0; i < keyValues.Length && hasPrimaryValues; i++)
-                               {
-                                       if(PrimaryKey[i].Ordinal < values.Length)
-                                               keyValues[i] = values[PrimaryKey[i].Ordinal];
-                                       else
-                                               hasPrimaryValues = false;
-                               }
-                               
-                               if (hasPrimaryValues){
-                                       // find the row in the table.
-                                       row = Rows.Find(keyValues);
-                               }
-                               
-                               if (row == null)
-                                       row = Rows.Add (values);
-                               else
-                                       row.ItemArray = values;
-                               
-                               if (fAcceptChanges)
-                                       row.AcceptChanges ();
-                       }
-                               
-                       return row;
-               }
-  
-               internal DataRow LoadDataRow(IDataRecord record, int[] mapping, bool fAcceptChanges)
-               {
-                       DataRow row = null;
-                       if (PrimaryKey.Length == 0) {
-                               row = NewRow();
-                               row.SetValuesFromDataRecord(record, mapping);
-                               Rows.Add (row);
-  
-                               if (fAcceptChanges) {
-                                       row.AcceptChanges();
-                               }
-                       }
-                       else {
-                               bool hasPrimaryValues = true;
-                               int tmpRecord = this.RecordCache.NewRecord();
-                               try {
-                                       for (int i = 0; i < PrimaryKey.Length && hasPrimaryValues; i++) {
-                                               DataColumn primaryKeyColumn = PrimaryKey[i];
-                                               int ordinal = primaryKeyColumn.Ordinal;
-                                               if(mapping [ordinal] >= 0) {
-                                                       primaryKeyColumn.DataContainer.SetItemFromDataRecord(tmpRecord,record,mapping[ordinal]);
-                                               }
-                                               else {
-                                                       hasPrimaryValues = false;
-                                               }
-                                       }
-                                       
-                                       if (hasPrimaryValues) {
-                                               // find the row in the table.
-                                               row = Rows.Find(tmpRecord, PrimaryKey.Length);
-                                       }
-                               }
-                               finally {
-                                       this.RecordCache.DisposeRecord(tmpRecord);
-                               }
-  
-                               if (row == null) {
-                                       row = NewRow();
-                                       row.SetValuesFromDataRecord(record, mapping);
-                                       Rows.Add (row);
-                               }
-                               else {
-                                       row.SetValuesFromDataRecord(record, mapping);
-                               }
-                               
-                               if (fAcceptChanges) {
-                                       row.AcceptChanges();
-                               }
-                       }                               
-                       return row;
-               }
-  
-  #if NET_2_0
-                  /// <summary>
-                  ///     Loads the given values into an existing row if matches or creates
-                  ///     the new row popluated with the values.
-                  /// </summary>
-                  /// <remarks>
-                  ///     This method searches for the values using primary keys and it first
-                  ///     searches using the original values of the rows and if not found, it
-                  ///     searches using the current version of the row.
-                  /// </remarks>
-               public DataRow LoadDataRow (object [] values, LoadOption loadOption)
-               {
-                          DataRow row  = null;
-                          bool new_row = false;
-                          
-                          // Find Data DataRow
-                          if (this.PrimaryKey.Length > 0) {
-                                  object [] keyValues = new object [this.PrimaryKey.Length];
-                                  for (int i = 0; i < keyValues.Length; i++)
-                                          keyValues [i] = values [this.PrimaryKey [i].Ordinal];
-                                  row = this.Rows.Find (keyValues, DataRowVersion.Original );
-                                  if (row == null) 
-                                          row = this.Rows.Find (keyValues, DataRowVersion.Current);
-                          }
-                                  
-                          // If not found, add new row
-                          if (row == null) {
-                                  row = this.NewRow ();
-                                  new_row = true;
-                          }
-  
-                          bool deleted = row.RowState == DataRowState.Deleted;
-  
-                          if (deleted && loadOption == LoadOption.OverwriteChanges)
-                                  row.RejectChanges ();                        
-  
-                          row.Load (values, loadOption, new_row);
-  
-                          if (deleted && loadOption == LoadOption.Upsert) {
-                                  row = this.NewRow ();
-                                  row.Load (values, loadOption, new_row = true);
-                          }
-  
-                          if (new_row) {
-                                  this.Rows.Add (row);
-                                  if (loadOption == LoadOption.OverwriteChanges ||
-                                      loadOption == LoadOption.PreserveChanges) {
-                                          row.AcceptChanges ();
-                                  }
-                          }
-  
-                          return row;
-               }
-  
-               [MonoTODO]
-               public void Merge (DataTable table)
-               {
-                       throw new NotImplementedException ();
-               }
-  
-               [MonoTODO]
-               public void Merge (DataTable table, bool preserveChanges)
-               {
-                       throw new NotImplementedException ();
-               }
-  
-               [MonoTODO]
-               public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
-               {
-                       throw new NotImplementedException ();
-               }
-  #endif
-  
-               /// <summary>
-               /// Creates a new DataRow with the same schema as the table.
-               /// </summary>
-               public DataRow NewRow () 
-               {
-                       // initiate only one row builder.
-                       if (_rowBuilder == null)
-                               _rowBuilder = new DataRowBuilder (this, 0, 0);
-                       
-                       // new row get id -1.
-                       _rowBuilder._rowId = -1;
-  
-                       // initialize default values row for the first time
-                       if ( _defaultValuesRowIndex == -1 ) {
-                               _defaultValuesRowIndex = RecordCache.NewRecord();
-                               foreach(DataColumn column in Columns) {
-                                       column.DataContainer[_defaultValuesRowIndex] = column.DefaultValue;
-                               }
-                       }
-  
-                       return this.NewRowFromBuilder (_rowBuilder);
-               }
-  
-               /// <summary>
-               /// This member supports the .NET Framework infrastructure
-               ///  and is not intended to be used directly from your code.
-               /// </summary>
-               protected internal DataRow[] NewRowArray (int size) 
-               {
-                       return (DataRow[]) Array.CreateInstance (GetRowType (), size);
-               }
-  
-               /// <summary>
-               /// Creates a new row from an existing row.
-               /// </summary>
-               protected virtual DataRow NewRowFromBuilder (DataRowBuilder builder) 
-               {
-                       return new DataRow (builder);
-               }
-               
-               internal DataRow NewNotInitializedRow()
-               {
-                       return new DataRow(this,-1);
-               }
-  
-  #if NET_2_0
-               [MonoTODO]
-               XmlReadMode ReadXml (Stream stream)
-               {
-                       throw new NotImplementedException ();
-               }
-  
-               public void ReadXmlSchema (Stream stream)
-               {
-                       ReadXmlSchema (new XmlTextReader (stream));
-               }
-  
-               public void ReadXmlSchema (TextReader reader)
-               {
-                       ReadXmlSchema (new XmlTextReader (reader));
-               }
-  
-               public void ReadXmlSchema (string fileName)
-               {
-                       XmlTextReader reader = null;
-                       try {
-                               reader = new XmlTextReader (fileName);
-                               ReadXmlSchema (reader);
-                       } finally {
-                               if (reader != null)
-                                       reader.Close ();
-                       }
-               }
-  
-               public void ReadXmlSchema (XmlReader reader)
-               {
-                       DataSet ds = new DataSet ();
-                       new XmlSchemaDataImporter (ds, reader).Process ();
-                       DataTable target = null;
-                       if (TableName == String.Empty) {
-                               if (ds.Tables.Count > 0)
-                                       target = ds.Tables [0];
-                       }
-                       else {
-                               target = ds.Tables [TableName];
-                               if (target == null)
-                                       throw new ArgumentException (String.Format ("DataTable '{0}' does not match to any DataTable in source.", TableName));
-                       }
-                       if (target != null)
-                               target.CopyProperties (this);
-               }
-  #endif
-  
-               /// <summary>
-               /// Rolls back all changes that have been made to the 
-               /// table since it was loaded, or the last time AcceptChanges
-               ///  was called.
-               /// </summary>
-               public void RejectChanges () 
-               {       
-                       for (int i = _rows.Count - 1; i >= 0; i--) {
-                               DataRow row = _rows [i];
-                               if (row.RowState != DataRowState.Unchanged)
-                                       _rows [i].RejectChanges ();
-                       }
-               }
-  
-               /// <summary>
-               /// Resets the DataTable to its original state.
-               /// </summary>          
-               public virtual void Reset () 
-               {
-                       Clear();
-                       while (ParentRelations.Count > 0)
-                       {
-                               if (dataSet.Relations.Contains(ParentRelations[ParentRelations.Count - 1].RelationName))
-                                       dataSet.Relations.Remove(ParentRelations[ParentRelations.Count - 1]);
-                       }
-  
-                       while (ChildRelations.Count > 0)
-                       {
-                               if (dataSet.Relations.Contains(ChildRelations[ChildRelations.Count - 1].RelationName))
-                                       dataSet.Relations.Remove(ChildRelations[ChildRelations.Count - 1]);
-                       }
-                       Constraints.Clear();
-                       Columns.Clear();
-               }
-  
-               /// <summary>
-               /// Gets an array of all DataRow objects.
-               /// </summary>
-               public DataRow[] Select () 
-               {
-                       return Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);
-               }
-  
-               /// <summary>
-               /// Gets an array of all DataRow objects that match 
-               /// the filter criteria in order of primary key (or 
-               /// lacking one, order of addition.)
-               /// </summary>
-               public DataRow[] Select (string filterExpression) 
-               {
-                       return Select(filterExpression, String.Empty, DataViewRowState.CurrentRows);
-               }
-  
-               /// <summary>
-               /// Gets an array of all DataRow objects that 
-               /// match the filter criteria, in the the 
-               /// specified sort order.
-               /// </summary>
-               public DataRow[] Select (string filterExpression, string sort) 
-               {
-                       return Select(filterExpression, sort, DataViewRowState.CurrentRows);
-               }
-  
-               /// <summary>
-               /// Gets an array of all DataRow objects that match
-               /// the filter in the order of the sort, that match 
-               /// the specified state.
-               /// </summary>
-               [MonoTODO]
-               public DataRow[] Select(string filterExpression, string sort, DataViewRowState recordStates) 
-               {
-                       if (filterExpression == null)
-                               filterExpression = String.Empty;
-  
-                       IExpression filter = null;
-                       if (filterExpression != String.Empty) {
-                               Parser parser = new Parser ();
-                               filter = parser.Compile (filterExpression);
-                       }
-                       SortableColumn[] sortableColumns = null;
-                       if (sort != null && !sort.Equals(String.Empty))
-                               sortableColumns = SortableColumn.ParseSortString (this, sort, true);
-  
-                       return Select (filter, sortableColumns, recordStates);
-               }
-  
-               internal DataRow [] Select (IExpression filter, SortableColumn [] sortableColumns, DataViewRowState recordStates)
-               {
-                       ArrayList rowList = new ArrayList();
-                       int recordStateFilter = GetRowStateFilter(recordStates);
-                       foreach (DataRow row in Rows) {
-                               if (((int)row.RowState & recordStateFilter) != 0) {
-                                       if (filter != null && !filter.EvalBoolean (row))
-                                               continue;
-                                       rowList.Add (row);
-                               }
-                       }
-  
-                       DataRow[] dataRows = (DataRow[])rowList.ToArray(GetRowType ());
-  
-                       if (sortableColumns != null) {
-                               RowSorter rowSorter = new RowSorter (this, sortableColumns);
-                               dataRows = rowSorter.SortRows (dataRows);
-  
-                               sortableColumns = null;
-                               rowSorter = null;
-                       }
-  
-                       return dataRows;
-               }
-  
-               internal void AddIndex (Index index)
-               {
-                       if (_indexes == null)
-                               _indexes = new ArrayList();
-  
-                       _indexes.Add (index);
-               }
-  
-               internal void RemoveIndex (Index indx)
-               {
-                       _indexes.Remove (indx);
-               }
-  
-               internal Index GetIndexByColumns (DataColumn[] columns)
-               {
-                       return GetIndexByColumns(columns,false,false);
-               }
-  
-  //           internal Index GetIndexByColumnsExtended(DataColumn[] columns)
-  //           {
-  //                   DataColumn[] pkColumns = this.PrimaryKey;
-  //                   if((pkColumns != null) && (pkColumns.Length > 0)) {
-  //                           DataColumn[] cols = new DataColumn[columns.Length + pkColumns.Length];                                  
-  //                           Array.Copy(columns,0,cols,0,columns.Length);
-  //                           Array.Copy(pkColumns,0,cols,columns.Length,pkColumns.Length);
-  //
-  //                           return _getIndexByColumns(cols,false,false);
-  //                   } else {
-  //                           return null;
-  //                   }
-  //           }
-  
-               internal Index GetIndexByColumns (DataColumn[] columns, bool unique)
-               {
-                       return GetIndexByColumns(columns,unique,true);
-               }
-  
-  //           internal Index GetIndexByColumnsExtended(DataColumn[] columns, bool unique)
-  //           {
-  //                   DataColumn[] pkColumns = this.PrimaryKey;
-  //                   if((pkColumns != null) && (pkColumns.Length > 0)) {
-  //                           DataColumn[] cols = new DataColumn[columns.Length + pkColumns.Length];                                  
-  //                           Array.Copy(columns,0,cols,0,columns.Length);
-  //                           Array.Copy(pkColumns,0,cols,columns.Length,pkColumns.Length);
-  //
-  //                           return _getIndexByColumns(cols,unique,true);
-  //                   } else  {
-  //                           return null;
-  //                   }
-  //           }
-  
-               internal Index GetIndexByColumns(DataColumn[] columns, bool unique, bool useUnique)
-               {
-                       if (_indexes != null) {
-                               foreach (Index indx in _indexes) {
-                                       bool found = false;
-                                       if ((!useUnique) || ((useUnique)&& (indx.IsUnique))) {
-                                               found = DataColumn.AreColumnSetsTheSame (indx.Columns, columns);
-                                       }
-                                       if (found)
-                                               return indx;
-                               }
-                       }
-  
-                       return null;
-               }
-  
-               internal void DeleteRowFromIndexes (DataRow row)
-               {
-                       if (_indexes != null) {
-                               foreach (Index indx in _indexes) {
-                                       indx.Delete (row);
-                               }
-                       }
-               }
-  
-               private static int GetRowStateFilter(DataViewRowState recordStates)
-               {
-                       int flag = 0;
-  
-                       if ((recordStates & DataViewRowState.Added) != 0)
-                               flag |= (int)DataRowState.Added;
-                       if ((recordStates & DataViewRowState.Deleted) != 0)
-                               flag |= (int)DataRowState.Deleted;
-                       if ((recordStates & DataViewRowState.ModifiedCurrent) != 0)
-                               flag |= (int)DataRowState.Modified;
-                       if ((recordStates & DataViewRowState.ModifiedOriginal) != 0)
-                               flag |= (int)DataRowState.Modified;
-                       if ((recordStates & DataViewRowState.Unchanged) != 0)
-                               flag |= (int)DataRowState.Unchanged;
-  
-                       return flag;
-               }
-  
-               /// <summary>
-               /// Gets the TableName and DisplayExpression, if 
-               /// there is one as a concatenated string.
-               /// </summary>
-               public override string ToString() 
-               {
-                       //LAMESPEC: spec says concat the two. impl puts a 
-                       //plus sign infront of DisplayExpression
-                       string retVal = TableName;
-                       if(DisplayExpression != null && DisplayExpression != "")
-                               retVal += " + " + DisplayExpression;
-                       return retVal;
-               }
-  
-  #if NET_2_0
-               private XmlWriterSettings GetWriterSettings ()
-               {
-                       XmlWriterSettings s = new XmlWriterSettings ();
-                       s.Indent = true;
-                       return s;
-               }
-  
-               public void WriteXml (Stream stream)
-               {
-                       WriteXml (stream, XmlWriteMode.IgnoreSchema);
-               }
-  
-               public void WriteXml (TextWriter writer)
-               {
-                       WriteXml (writer, XmlWriteMode.IgnoreSchema);
-               }
-  
-               public void WriteXml (XmlWriter writer)
-               {
-                       WriteXml (writer, XmlWriteMode.IgnoreSchema);
-               }
-  
-               public void WriteXml (string fileName)
-               {
-                       WriteXml (fileName, XmlWriteMode.IgnoreSchema);
-               }
-  
-               public void WriteXml (Stream stream, XmlWriteMode mode)
-               {
-                       WriteXml (XmlWriter.Create (stream, GetWriterSettings ()), mode);
-               }
-  
-               public void WriteXml (TextWriter writer, XmlWriteMode mode)
-               {
-                       WriteXml (XmlWriter.Create (writer, GetWriterSettings ()), mode);
-               }
-  
-               [MonoTODO]
-               public void WriteXml (XmlWriter writer, XmlWriteMode mode)
-               {
-                       throw new NotImplementedException ();
-               }
-  
-               public void WriteXml (string fileName, XmlWriteMode mode)
-               {
-                       XmlWriter xw = null;
-                       try {
-                               xw = XmlWriter.Create (fileName, GetWriterSettings ());
-                               WriteXml (xw, mode);
-                       } finally {
-                               if (xw != null)
-                                       xw.Close ();
-                       }
-               }
-  
-               public void WriteXmlSchema (Stream stream)
-               {
-                       WriteXmlSchema (XmlWriter.Create (stream, GetWriterSettings ()));
-               }
-  
-               public void WriteXmlSchema (TextWriter writer)
-               {
-                       WriteXmlSchema (XmlWriter.Create (writer, GetWriterSettings ()));
-               }
-  
-               public void WriteXmlSchema (XmlWriter writer)
-               {
-                       DataSet ds = DataSet;
-                       DataSet tmp = null;
-                       try {
-                               if (ds == null) {
-                                       tmp = ds = new DataSet ();
-                                       ds.Tables.Add (this);
-                               }
-                               DataTableCollection col = new DataTableCollection (ds);
-                               col.Add (this);
-                               XmlSchemaWriter.WriteXmlSchema (ds, writer, col, null);
-                       } finally {
-                               if (tmp != null)
-                                       ds.Tables.Remove (this);
-                       }
-               }
-  
-               public void WriteXmlSchema (string fileName)
-               {
-                       XmlWriter xw = null;
-                       try {
-                               xw = XmlWriter.Create (fileName, GetWriterSettings ());
-                               WriteXmlSchema (xw);
-                       } finally {
-                               if (xw != null)
-                                       xw.Close ();
-                       }
-               }
-  #endif
-               
-               #region Events 
-               
-               /// <summary>
-               /// Raises the ColumnChanged event.
-               /// </summary>
-               protected virtual void OnColumnChanged (DataColumnChangeEventArgs e) {
-                       if (null != ColumnChanged) {
-                               ColumnChanged (this, e);
-                       }
-               }
-  
-               internal void RaiseOnColumnChanged (DataColumnChangeEventArgs e) {
-                       OnColumnChanged(e);
-               }
-  
-  #if NET_2_0
-                  /// <summary>
-               /// Raises TableCleared Event and delegates to subscribers
-               /// </summary>
-               protected virtual void OnTableCleared (DataTableClearEventArgs e) {
-                       if (TableCleared != null)
-                               TableCleared (this, e);
-               }
-  #endif // NET_2_0
-  
-               /// <summary>
-               /// Raises the ColumnChanging event.
-               /// </summary>
-               protected virtual void OnColumnChanging (DataColumnChangeEventArgs e) {
-                       if (null != ColumnChanging) {
-                               ColumnChanging (this, e);
-                       }
-               }
-  
-               /// <summary>
-               /// Raises the PropertyChanging event.
-               /// </summary>
-               [MonoTODO]
-               protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent) {
-                       //      if (null != PropertyChanging)
-                       //      {
-                       //              PropertyChanging (this, e);
-                       //      }
-               }
-  
-               /// <summary>
-               /// Notifies the DataTable that a DataColumn is being removed.
-               /// </summary>
-               [MonoTODO]
-               protected internal virtual void OnRemoveColumn (DataColumn column) {
-               }
-  
-  
-               /// <summary>
-               /// Raises the RowChanged event.
-               /// </summary>
-               protected virtual void OnRowChanged (DataRowChangeEventArgs e) {
-                       if (null != RowChanged) {
-                               RowChanged(this, e);
-                       }
-               }
-  
-  
-               /// <summary>
-               /// Raises the RowChanging event.
-               /// </summary>
-               protected virtual void OnRowChanging (DataRowChangeEventArgs e) {
-                       if (null != RowChanging) {
-                               RowChanging(this, e);
-                       }
-               }
-  
-               /// <summary>
-               /// Raises the RowDeleted event.
-               /// </summary>
-               protected virtual void OnRowDeleted (DataRowChangeEventArgs e) {
-                       if (null != RowDeleted) {
-                               RowDeleted(this, e);
-                       }
-               }
-  
-               /// <summary>
-               /// Raises the RowDeleting event.
-               /// </summary>
-               protected virtual void OnRowDeleting (DataRowChangeEventArgs e) {
-                       if (null != RowDeleting) {
-                               RowDeleting(this, e);
-                       }
-               }
-  
-               [MonoTODO]
-               private DataColumn CopyColumn (DataColumn Column) {
-                       DataColumn Copy = new DataColumn ();
-  
-                       // Copy all the properties of column
-                       Copy.Caption = Column.Caption;
-                       Copy.ColumnMapping = Column.ColumnMapping;
-                       Copy.ColumnName = Column.ColumnName;
-                       //Copy.Container
-                       Copy.DataType = Column.DataType;
-                       Copy.DefaultValue = Column.DefaultValue;                        
-                       Copy.Expression = Column.Expression;
-                       //Copy.ExtendedProperties
-                       Copy.MaxLength = Column.MaxLength;
-                       Copy.Namespace = Column.Namespace;
-                       Copy.Prefix = Column.Prefix;
-                       Copy.ReadOnly = Column.ReadOnly;
-                       //Copy.Site
-                       //we do not copy the unique value - it will be copyied when copying the constraints.
-                       //Copy.Unique = Column.Unique;
-  
-                       // At least AutoIncrement must be set after DefaultValue
-                       Copy.AllowDBNull = Column.AllowDBNull;
-                       Copy.AutoIncrement = Column.AutoIncrement;
-                       Copy.AutoIncrementSeed = Column.AutoIncrementSeed;
-                       Copy.AutoIncrementStep = Column.AutoIncrementStep;
-                       
-                       return Copy;
-               }                       
-  
-               /// <summary>
-               /// Occurs when after a value has been changed for 
-               /// the specified DataColumn in a DataRow.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs when a value has been changed for this column.")]
-               public event DataColumnChangeEventHandler ColumnChanged;
-  
-               /// <summary>
-               /// Occurs when a value is being changed for the specified 
-               /// DataColumn in a DataRow.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Occurs when a value has been submitted for this column. The user can modify the proposed value and should throw an exception to cancel the edit.")]
-               public event DataColumnChangeEventHandler ColumnChanging;
-  
-               /// <summary>
-               /// Occurs after a DataRow has been changed successfully.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs after a row in the table has been successfully edited.")]
-               public event DataRowChangeEventHandler RowChanged;
-  
-               /// <summary>
-               /// Occurs when a DataRow is changing.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs when the row is being changed so that the event handler can modify or cancel the change. The user can modify values in the row and should throw an  exception to cancel the edit.")]
-               public event DataRowChangeEventHandler RowChanging;
-  
-               /// <summary>
-               /// Occurs after a row in the table has been deleted.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs after a row in the table has been successfully deleted.")] 
-               public event DataRowChangeEventHandler RowDeleted;
-  
-               /// <summary>
-               /// Occurs before a row in the table is about to be deleted.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs when a row in the table marked for deletion. Throw an exception to cancel the deletion.")]
-               public event DataRowChangeEventHandler RowDeleting;
-  
-  #if NET_2_0
-               /// <summary>
-               /// Occurs after the Clear method is called on the datatable.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs when the rows in a table is cleared . Throw an exception to cancel the deletion.")]
-               public event DataTableClearEventHandler TableCleared;
-  #endif // NET_2_0
-  
-               #endregion // Events
-  
-               /// <summary>
-               ///  Removes all UniqueConstraints
-               /// </summary>
-               private void RemoveUniqueConstraints () 
-               {
-                       foreach (Constraint Cons in Constraints) {
-                               
-                               if (Cons is UniqueConstraint) {
-                                       Constraints.Remove (Cons);
-                                       break;
-                               }
-                       }
-                       
-                       UniqueConstraint.SetAsPrimaryKey(this.Constraints, null);
-               }
-  
-               internal class RowSorter : IComparer 
-               {
-                       private DataTable table;
-                       private SortableColumn[] sortColumns;
-                       
-                       internal RowSorter(DataTable table,
-                                       SortableColumn[] sortColumns) 
-                       {
-                               this.table = table;
-                               this.sortColumns = sortColumns;
-                       }
-  
-                       public SortableColumn[] SortColumns {
-                               get {
-                                       return sortColumns;
-                               }
-                       }
-                       
-                       public DataRow[] SortRows (DataRow [] rowsToSort) 
-                       {
-                               Array.Sort (rowsToSort, this);
-                               return rowsToSort;
-                       }
-  
-                       int IComparer.Compare (object x, object y) 
-                       {
-                               if(x == null)
-                                       throw new SystemException ("Object to compare is null: x");
-                               if(y == null)
-                                       throw new SystemException ("Object to compare is null: y");
-                               if(!(x is DataRow))
-                                       throw new SystemException ("Object to compare is not DataRow: x is " + x.GetType().ToString());
-                               if(!(y is DataRow))
-                                       throw new SystemException ("Object to compare is not DataRow: y is " + x.GetType().ToString());
-  
-                               if (x == y)
-                                       return 0;
-  
-                               DataRow rowx = (DataRow) x;
-                               DataRow rowy = (DataRow) y;
-  
-                               for(int i = 0; i < sortColumns.Length; i++) {
-                                       SortableColumn sortColumn = sortColumns[i];
-                                       DataColumn dc = sortColumn.Column;
-  
-                                       int result = dc.CompareValues(
-                                               rowx.IndexFromVersion(DataRowVersion.Default),
-                                               rowy.IndexFromVersion(DataRowVersion.Default));
-  
-                                       if (result != 0) {
-                                               if (sortColumn.SortDirection == ListSortDirection.Ascending) {
-                                                       return result;
-                                               }
-                                               else {
-                                                       return -result;
-                                               }
-                                       }
-                               }
-                               return x.GetHashCode () - y.GetHashCode ();
-                       }
-               }
-  
-               /// <summary>
-               /// Creates new index for a table
-               /// </summary>
-               internal Index CreateIndex(string name, DataColumn[] columns, bool unique)
-               {
-                       // first check whenever index exists on the columns
-                       Index idx = this.GetIndexByColumns(columns);
-                       if(idx != null) {
-                       // if index on this columns already exists - return it
-                               return idx;
-                       }
-  
-                       // create new index
-                       Index newIndex = new Index(name,this,columns,unique);
-  
-                       //InitializeIndex (newIndex);                   
-  
-                       // add new index to table indexes
-                       this.AddIndex(newIndex);
-                       return newIndex;
-               }
-  
-  //           /// <summary>
-  //           /// Creates new extended index for a table
-  //           /// </summary>
-  //           internal Index CreateIndexExtended(string name, DataColumn[] columns, bool unique)
-  //           {
-  //                   // first check whenever extended index exists on the columns
-  //                   Index idx = this.GetIndexByColumnsExtended(columns);
-  //                   if(idx != null) {
-  //                           // if extended index on this columns already exists - return it
-  //                           return idx;
-  //                   }
-  //
-  //                   DataColumn[] pkColumns = this.PrimaryKey;
-  //                   if((pkColumns != null) && (pkColumns.Length > 0)) {
-  //                           DataColumn[] cols = new DataColumn[columns.Length + pkColumns.Length];                                  
-  //                           Array.Copy(columns,0,cols,0,columns.Length);
-  //                           Array.Copy(pkColumns,0,cols,columns.Length,pkColumns.Length);
-  //                           return this.CreateIndex(name, cols, unique);
-  //                   } 
-  //                   else {
-  //                           throw new InvalidOperationException("Can not create extended index if the primary key is null or primary key does not contains any row");
-  //                   }
-  //           }
-  
-  //           /// <summary>
-  //           /// Drops extended index if it is not referenced anymore
-  //           /// by any of table constraints
-  //           /// </summary>
-  //           internal void DropIndexExtended(DataColumn[] columns)
-  //           {
-  //                   // first check whenever extended index exists on the columns
-  //                   Index index = this.GetIndexByColumnsExtended(columns);
-  //                   if(index == null) {
-  //                           // if no extended index on this columns exists - do nothing
-  //                           return;
-  //                   }
-  //                   this.DropIndex(index);
-  //           }
-  
-               /// <summary>
-               /// Drops index specified by columns if it is not referenced anymore
-               /// by any of table constraints
-               /// </summary>
-               internal void DropIndex(DataColumn[] columns)
-               {
-                       // first check whenever index exists for the columns
-                       Index index = this.GetIndexByColumns(columns);
-                       if(index == null) {
-                       // if no index on this columns already exists - do nothing
-                               return;
-                       }
-                       this.DropIndex(index);
-               }
-  
-               internal void DropIndex(Index index)
-               {
-                       // loop through table constraints and checks 
-                       foreach(Constraint constraint in Constraints) {
-                               // if we found another reference to the index we do not remove the index.
-                               if (index == constraint.Index)
-                                       return; 
-                       }
-                       
-                       this.RemoveIndex(index);
-               }
-  
-               internal void InitializeIndex (Index indx)
-               {
-                       DataRow[] rows = new DataRow[this.Rows.Count];
-                       this.Rows.CopyTo (rows, 0);
-                       indx.Root = null;
-                       // fill index with table rows
-                       foreach(DataRow row in this.Rows) {
-                               if(row.RowState != DataRowState.Deleted) {
-                                       indx.Insert(new Node(row), DataRowVersion.Default);
-                               }
-                       }
-               }
-       }
-  
-       // to parse the sort string for DataTable:Select(expression,sort)
-       // into sortable columns (think ORDER BY, 
-       // such as, "customer ASC, price DESC" ), as well as DataView.Sort.
-       internal class SortableColumn 
-       {
-               private DataColumn col;
-               private ListSortDirection dir;
-  
-               internal SortableColumn (DataColumn column, 
-                                       ListSortDirection direction) 
-               {
-                       col = column;
-                       dir = direction;
-               }
-  
-               public DataColumn Column {
-                       get {
-                               return col;
-                       }
-               }
-  
-               public ListSortDirection SortDirection {
-                       get {
-                               return dir;
-                       }
-               }
-  
-               internal static SortableColumn[] ParseSortString (DataTable table, string sort, bool rejectNoResult)
-               {
-                       SortableColumn[] sortColumns = null;
-                       ArrayList columns = null;
-               
-                       if (sort != null && !sort.Equals ("")) {
-                               columns = new ArrayList ();
-                               string[] columnExpression = sort.Trim ().Split (new char[1] {','});
-                       
-                               for (int c = 0; c < columnExpression.Length; c++) {
-                                       string[] columnSortInfo = columnExpression[c].Trim ().Split (new char[1] {' '});
-                               
-                                       string columnName = columnSortInfo[0].Trim ();
-                                       string sortOrder = "ASC";
-                                       if (columnSortInfo.Length > 1) 
-                                               sortOrder = columnSortInfo[1].Trim ().ToUpper (table.Locale);
-                                       
-                                       ListSortDirection sortDirection = ListSortDirection.Ascending;
-                                       switch (sortOrder) {
-                                       case "ASC":
-                                               sortDirection = ListSortDirection.Ascending;
-                                               break;
-                                       case "DESC":
-                                               sortDirection = ListSortDirection.Descending;
-                                               break;
-                                       default:
-                                               throw new IndexOutOfRangeException ("Could not find column: " + columnExpression[c]);
-                                       }
-                                       Int32 ord = 0;
-                                       try {
-                                               ord = Int32.Parse (columnName);
-                                       }
-                                       catch (FormatException) {
-                                               ord = -1;
-                                       }
-                                       DataColumn dc = null;
-                                       if (ord == -1)                          
-                                               dc = table.Columns [columnName];
-                                       else
-                                               dc = table.Columns [ord];
-                                       SortableColumn sortCol = new SortableColumn (dc,sortDirection);
-                                       columns.Add (sortCol);
-                               }       
-                               sortColumns = (SortableColumn[]) columns.ToArray (typeof (SortableColumn));
-                       }               
-  
-                       if (rejectNoResult) {
-                               if (sortColumns == null)
-                                       throw new SystemException ("sort expression result is null");
-                               if (sortColumns.Length == 0)
-                                       throw new SystemException("sort expression result is 0");
-                       }
-                       return sortColumns;
-               }
-       }
-  
-  }
+  //\r
+  // System.Data.DataTable.cs\r
+  //\r
+  // Author:\r
+  //   Franklin Wise <gracenote@earthlink.net>\r
+  //   Christopher Podurgiel (cpodurgiel@msn.com)\r
+  //   Daniel Morgan <danmorg@sc.rr.com>\r
+  //   Rodrigo Moya <rodrigo@ximian.com>\r
+  //   Tim Coleman (tim@timcoleman.com)\r
+  //   Ville Palo <vi64pa@koti.soon.fi>\r
+++//   Sureshkumar T <tsureshkumar@novell.com>\r
+  //   Konstantin Triger <kostat@mainsoft.com>\r
+  //\r
+  // (C) Chris Podurgiel\r
+  // (C) Ximian, Inc 2002\r
+  // Copyright (C) Tim Coleman, 2002-2003\r
+  // Copyright (C) Daniel Morgan, 2002-2003\r
+  //\r
+  \r
+  //\r
+  // Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+  //\r
+  // Permission is hereby granted, free of charge, to any person obtaining\r
+  // a copy of this software and associated documentation files (the\r
+  // "Software"), to deal in the Software without restriction, including\r
+  // without limitation the rights to use, copy, modify, merge, publish,\r
+  // distribute, sublicense, and/or sell copies of the Software, and to\r
+  // permit persons to whom the Software is furnished to do so, subject to\r
+  // the following conditions:\r
+  // \r
+  // The above copyright notice and this permission notice shall be\r
+  // included in all copies or substantial portions of the Software.\r
+  // \r
+  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+  //\r
+  \r
+  using System;\r
+  using System.Data.Common;\r
+  using System.Collections;\r
+  using System.ComponentModel;\r
+  using System.Globalization;\r
+  using System.IO;\r
+  using System.Runtime.Serialization;\r
+  using System.Xml;\r
+  using System.Xml.Schema;\r
+  using Mono.Data.SqlExpressions;\r
+  \r
+  namespace System.Data {\r
+       //[Designer]\r
+       [ToolboxItem (false)]\r
+       [DefaultEvent ("RowChanging")]\r
+       [DefaultProperty ("TableName")]\r
+       [DesignTimeVisible (false)]\r
+       [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DataTableEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]\r
+       [Serializable]\r
+       public class DataTable : MarshalByValueComponent, IListSource, ISupportInitialize, ISerializable \r
+       {\r
+               #region Fields\r
+  \r
+               internal DataSet dataSet;   \r
+               \r
+               private bool _caseSensitive;\r
+               private DataColumnCollection _columnCollection;\r
+               private ConstraintCollection _constraintCollection;\r
+               // never access it. Use DefaultView.\r
+               private DataView _defaultView = null;\r
+  \r
+               private string _displayExpression;\r
+               private PropertyCollection _extendedProperties;\r
+               private bool _hasErrors;\r
+               private CultureInfo _locale;\r
+               private int _minimumCapacity;\r
+               private string _nameSpace;\r
+               private DataRelationCollection _childRelations; \r
+               private DataRelationCollection _parentRelations;\r
+               private string _prefix;\r
+               private UniqueConstraint _primaryKeyConstraint;\r
+               private DataRowCollection _rows;\r
+               private ISite _site;\r
+               private string _tableName;\r
+               private bool _containsListCollection;\r
+               private string _encodedTableName;\r
+               internal bool _duringDataLoad;\r
+               internal bool _nullConstraintViolationDuringDataLoad;\r
+               private bool dataSetPrevEnforceConstraints;\r
+               private bool dataTablePrevEnforceConstraints;\r
+               private bool enforceConstraints = true;\r
+               private DataRowBuilder _rowBuilder;\r
+               private ArrayList _indexes;\r
+               private RecordCache _recordCache;\r
+               private int _defaultValuesRowIndex = -1;\r
+               protected internal bool fInitInProgress;\r
+  \r
+               // If CaseSensitive property is changed once it does not anymore follow owner DataSet's \r
+               // CaseSensitive property. So when you lost you virginity it's gone for ever\r
+               private bool _virginCaseSensitive = true;\r
+               \r
+               private PropertyDescriptorCollection _propertyDescriptorsCache;\r
+               static DataColumn[] _emptyColumnArray = new DataColumn[0];\r
+               \r
+               #endregion //Fields\r
+               \r
+               /// <summary>\r
+               /// Initializes a new instance of the DataTable class with no arguments.\r
+               /// </summary>\r
+               public DataTable () \r
+               {\r
+                       dataSet = null;\r
+                       _columnCollection = new DataColumnCollection(this);\r
+                       _constraintCollection = new ConstraintCollection(this); \r
+                       _extendedProperties = new PropertyCollection();\r
+                       _tableName = "";\r
+                       _nameSpace = null;\r
+                       _caseSensitive = false;         //default value\r
+                       _displayExpression = null;\r
+                       _primaryKeyConstraint = null;\r
+                       _site = null;\r
+                       _rows = new DataRowCollection (this);\r
+                       _indexes = new ArrayList();\r
+                       _recordCache = new RecordCache(this);\r
+                       \r
+                       //LAMESPEC: spec says 25 impl does 50\r
+                       _minimumCapacity = 50;\r
+                       \r
+                       _childRelations = new DataRelationCollection.DataTableRelationCollection (this);\r
+                       _parentRelations = new DataRelationCollection.DataTableRelationCollection (this);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Intitalizes a new instance of the DataTable class with the specified table name.\r
+               /// </summary>\r
+               public DataTable (string tableName) : this () \r
+               {\r
+                       _tableName = tableName;\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Initializes a new instance of the DataTable class with the SerializationInfo and the StreamingContext.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               protected DataTable (SerializationInfo info, StreamingContext context)\r
+                       : this () \r
+               {\r
+                       string schema = info.GetString ("XmlSchema");\r
+                       string data = info.GetString ("XmlDiffGram");\r
+                       \r
+                       DataSet ds = new DataSet ();\r
+                       ds.ReadXmlSchema (new StringReader (schema));\r
+                       ds.Tables [0].CopyProperties (this);\r
+                       ds = new DataSet ();\r
+                       ds.Tables.Add (this);\r
+                       ds.ReadXml (new StringReader (data), XmlReadMode.DiffGram);\r
+                       ds.Tables.Remove (this);\r
+  /* keeping for a while. With the change above, we shouldn't have to consider \r
+   * DataTable mode in schema inference/read.\r
+                       XmlSchemaMapper mapper = new XmlSchemaMapper (this);\r
+                       XmlTextReader xtr = new XmlTextReader(new StringReader (schema));\r
+                       mapper.Read (xtr);\r
+                       \r
+                       XmlDiffLoader loader = new XmlDiffLoader (this);\r
+                       xtr = new XmlTextReader(new StringReader (data));\r
+                       loader.Load (xtr);\r
+  */\r
+               }\r
+  \r
+  #if NET_2_0\r
+               public DataTable (string tableName, string tbNamespace)\r
+                       : this (tableName)\r
+               {\r
+                       _nameSpace = tbNamespace;\r
+               }\r
+  #endif\r
+  \r
+               /// <summary>\r
+               /// Indicates whether string comparisons within the table are case-sensitive.\r
+               /// </summary>\r
+               [DataSysDescription ("Indicates whether comparing strings within the table is case sensitive.")]        \r
+               public bool CaseSensitive {\r
+                       get { \r
+                               if (_virginCaseSensitive && dataSet != null)\r
+                                       return dataSet.CaseSensitive; \r
+                               else\r
+                                       return _caseSensitive;\r
+                               }\r
+                       set {\r
+                               if (_childRelations.Count > 0 || _parentRelations.Count > 0) {\r
+                                       throw new ArgumentException ("Cannot change CaseSensitive or Locale property. This change would lead to at least one DataRelation or Constraint to have different Locale or CaseSensitive settings between its related tables.");\r
+                               }\r
+                               _virginCaseSensitive = false;\r
+                               _caseSensitive = value; \r
+                               ResetCaseSensitiveIndexes();\r
+                       }\r
+               }\r
+               \r
+               internal ArrayList Indexes{\r
+                       get { return _indexes; }\r
+               }\r
+  \r
+               internal void ChangedDataColumn (DataRow dr, DataColumn dc, object pv) \r
+               {\r
+                       DataColumnChangeEventArgs e = new DataColumnChangeEventArgs (dr, dc, pv);\r
+                       OnColumnChanged(e);\r
+               }\r
+  \r
+               internal void ChangingDataColumn (DataRow dr, DataColumn dc, object pv) \r
+               {\r
+                       DataColumnChangeEventArgs e = new DataColumnChangeEventArgs (dr, dc, pv);\r
+                       OnColumnChanging (e);\r
+               }\r
+  \r
+               internal void DeletedDataRow (DataRow dr, DataRowAction action) \r
+               {\r
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);\r
+                       OnRowDeleted (e);\r
+               }\r
+  \r
+               internal void DeletingDataRow (DataRow dr, DataRowAction action) \r
+               {\r
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);\r
+                       OnRowDeleting(e);\r
+               }\r
+  \r
+               internal void ChangedDataRow (DataRow dr, DataRowAction action) \r
+               {\r
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);\r
+                       OnRowChanged (e);\r
+               }\r
+  \r
+               internal void ChangingDataRow (DataRow dr, DataRowAction action) \r
+               {\r
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);\r
+                       OnRowChanging (e);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets the collection of child relations for this DataTable.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Returns the child relations for this table.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public DataRelationCollection ChildRelations {\r
+                       get {\r
+                               return _childRelations;\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets the collection of columns that belong to this table.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The collection that holds the columns for this table.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
+               public DataColumnCollection Columns {\r
+                       get { return _columnCollection; }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets the collection of constraints maintained by this table.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("The collection that holds the constraints for this table.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
+               public ConstraintCollection Constraints {\r
+                       get { return _constraintCollection; }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets the DataSet that this table belongs to.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Indicates the DataSet to which this table belongs.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public DataSet DataSet {\r
+                       get { return dataSet; }\r
+               }\r
+  \r
+               \r
+  \r
+               /// <summary>\r
+               /// Gets a customized view of the table which may \r
+               /// include a filtered view, or a cursor position.\r
+               /// </summary>\r
+               [MonoTODO]      \r
+               [Browsable (false)]\r
+               [DataSysDescription ("This is the default DataView for the table.")]\r
+               public DataView DefaultView {\r
+                       get {\r
+                               if (_defaultView == null) {\r
+                                       lock(this){\r
+                                               if (_defaultView == null){\r
+                                                       if (dataSet != null)\r
+                                                               _defaultView = dataSet.DefaultViewManager.CreateDataView(this);\r
+                                                       else\r
+                                                               _defaultView = new DataView(this);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               return _defaultView;\r
+                       }\r
+               }\r
+               \r
+  \r
+               /// <summary>\r
+               /// Gets or sets the expression that will return \r
+               /// a value used to represent this table in the user interface.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The expression used to compute the data-bound value of this row.")]       \r
+               [DefaultValue ("")]\r
+               public string DisplayExpression {\r
+                       get { return _displayExpression == null ? "" : _displayExpression; }\r
+                       set { _displayExpression = value; }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets the collection of customized user information.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The collection that holds custom user information.")]\r
+               public PropertyCollection ExtendedProperties {\r
+                       get { return _extendedProperties; }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets a value indicating whether there are errors in \r
+               /// any of the_rows in any of the tables of the DataSet to \r
+               /// which the table belongs.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Returns whether the table has errors.")]\r
+               public bool HasErrors {\r
+                       get { \r
+                               // we can not use the _hasError flag because we do not know when to turn it off!\r
+                               for (int i = 0; i < _rows.Count; i++)\r
+                               {\r
+                                       if (_rows[i].HasErrors)\r
+                                               return true;\r
+                               }\r
+                               return false;\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets or sets the locale information used to \r
+               /// compare strings within the table.\r
+               /// </summary>\r
+               [DataSysDescription ("Indicates a locale under which to compare strings within the table.")]\r
+               public CultureInfo Locale {\r
+                       get { \r
+                               // if the locale is null, we check for the DataSet locale\r
+                               // and if the DataSet is null we return the current culture.\r
+                               // this way if DataSet locale is changed, only if there is no locale for \r
+                               // the DataTable it influece the Locale get;\r
+                               if (_locale != null)\r
+                                       return _locale;\r
+                               if (DataSet != null)\r
+                                       return DataSet.Locale;\r
+                               return CultureInfo.CurrentCulture;\r
+                       }\r
+                       set { \r
+                               if (_childRelations.Count > 0 || _parentRelations.Count > 0) {\r
+                                       throw new ArgumentException ("Cannot change CaseSensitive or Locale property. This change would lead to at least one DataRelation or Constraint to have different Locale or CaseSensitive settings between its related tables.");\r
+                               }\r
+                               if (_locale == null || !_locale.Equals(value))\r
+                                       _locale = value; \r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets or sets the initial starting size for this table.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates an initial starting size for this table.")]\r
+               [DefaultValue (50)]\r
+               public int MinimumCapacity {\r
+                       get { return _minimumCapacity; }\r
+                       set { _minimumCapacity = value; }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets or sets the namespace for the XML represenation \r
+               /// of the data stored in the DataTable.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the XML uri namespace for the elements contained in this table.")]\r
+               public string Namespace {\r
+                       get\r
+                       {\r
+                               if (_nameSpace != null)\r
+                               {\r
+                                       return _nameSpace;\r
+                               }\r
+                               if (DataSet != null)\r
+                               {\r
+                                       return DataSet.Namespace;\r
+                               }\r
+                               return String.Empty;\r
+                       }\r
+                       set { _nameSpace = value; }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets the collection of parent relations for \r
+               /// this DataTable.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Returns the parent relations for this table.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public DataRelationCollection ParentRelations {\r
+                       get {   \r
+                               return _parentRelations;\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets or sets the namespace for the XML represenation\r
+               ///  of the data stored in the DataTable.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the Prefix of the namespace used for this table in XML representation.")]\r
+               [DefaultValue ("")]\r
+               public string Prefix {\r
+                       get { return _prefix == null ? "" : _prefix; }\r
+                       set {\r
+                               // Prefix cannot contain any special characters other than '_' and ':'\r
+                               for (int i = 0; i < value.Length; i++) {\r
+                                       if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))\r
+                                               throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");\r
+                               }\r
+                               _prefix = value;\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets or sets an array of columns that function as \r
+               /// primary keys for the data table.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the column(s) that represent the primary key for this table.")]\r
+               [EditorAttribute ("Microsoft.VSDesigner.Data.Design.PrimaryKeyEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]\r
+               [TypeConverterAttribute ("System.Data.PrimaryKeyTypeConverter, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]\r
+               public DataColumn[] PrimaryKey {\r
+                       get {\r
+                               if (_primaryKeyConstraint == null) { \r
+                                       return new DataColumn[] {};\r
+                               }\r
+                               return _primaryKeyConstraint.Columns;\r
+                       }\r
+                       set {\r
+                               UniqueConstraint oldPKConstraint = _primaryKeyConstraint;\r
+                               \r
+                               // first check if value is the same as current PK.\r
+                               if (oldPKConstraint != null && DataColumn.AreColumnSetsTheSame(value, oldPKConstraint.Columns))\r
+                                       return;\r
+  \r
+                               // remove PK Constraint\r
+                               if(oldPKConstraint != null) {\r
+                                       _primaryKeyConstraint = null;\r
+                                       Constraints.Remove(oldPKConstraint);\r
+                               }\r
+                               \r
+                               if (value != null) {\r
+                                       //Does constraint exist for these columns\r
+                                       UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet(this.Constraints, (DataColumn[]) value);\r
+                               \r
+                                       //if constraint doesn't exist for columns\r
+                                       //create new unique primary key constraint\r
+                                       if (null == uc) {\r
+                                               foreach (DataColumn Col in (DataColumn[]) value) {\r
+                                                       if (Col.Table == null)\r
+                                                               break;\r
+  \r
+                                                       if (Columns.IndexOf (Col) < 0)\r
+                                                               throw new ArgumentException ("PrimaryKey columns do not belong to this table.");\r
+                                               }\r
+                                               // create constraint with primary key indication set to false\r
+                                               // to avoid recursion\r
+                                               uc = new UniqueConstraint( (DataColumn[]) value, false);                \r
+                                               Constraints.Add (uc);\r
+                                       }\r
+  \r
+                                       //set the constraint as the new primary key\r
+                                               UniqueConstraint.SetAsPrimaryKey(this.Constraints, uc);\r
+                                       _primaryKeyConstraint = uc;\r
+                               }                               \r
+                       }\r
+               }\r
+  \r
+               internal UniqueConstraint PrimaryKeyConstraint {\r
+                       get{\r
+                               return _primaryKeyConstraint;\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets the collection of_rows that belong to this table.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Indicates the collection that holds the rows of data for this table.")]   \r
+               public DataRowCollection Rows {\r
+                       get { return _rows; }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets or sets an System.ComponentModel.ISite \r
+               /// for the DataTable.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public override ISite Site {\r
+                       get { return _site; }\r
+                       set { _site = value; }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets or sets the name of the the DataTable.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the name used to look up this table in the Tables collection of a DataSet.")]\r
+               [DefaultValue ("")]     \r
+               [RefreshProperties (RefreshProperties.All)]\r
+               public string TableName {\r
+                       get { return _tableName == null ? "" : _tableName; }\r
+                       set { _tableName = value; }\r
+               }\r
+               \r
+               bool IListSource.ContainsListCollection {\r
+                       get {\r
+                               // the collection is a DataView\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               internal RecordCache RecordCache {\r
+                       get {\r
+                               return _recordCache;\r
+                       }\r
+               }\r
+               \r
+               private DataRowBuilder RowBuilder\r
+               {\r
+                       get\r
+                       {\r
+                               // initiate only one row builder.\r
+                               if (_rowBuilder == null)\r
+                                       _rowBuilder = new DataRowBuilder (this, -1, 0);\r
+                               else                    \r
+                                       // new row get id -1.\r
+                                       _rowBuilder._rowId = -1;\r
+  \r
+                               return _rowBuilder;\r
+                       }\r
+               }\r
+               \r
+               private bool EnforceConstraints {\r
+                       get { return enforceConstraints; }\r
+                       set {\r
+                               if (value != enforceConstraints) {\r
+                                       if (value) {\r
+                                               // reset indexes since they may be outdated\r
+                                               ResetIndexes();\r
+  \r
+                                               bool violatesConstraints = false;\r
+  \r
+                                               //FIXME: use index for AllowDBNull\r
+                                               for (int i = 0; i < Columns.Count; i++) {\r
+                                                       DataColumn column = Columns[i];\r
+                                                       if (!column.AllowDBNull) {\r
+                                                               for (int j = 0; j < Rows.Count; j++){\r
+                                                                       if (Rows[j].IsNull(column)) {\r
+                                                                               violatesConstraints = true;\r
+                                                                               Rows[j].RowError = String.Format("Column '{0}' does not allow DBNull.Value.", column.ColumnName);\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+  \r
+                                               if (violatesConstraints)\r
+                                                       Constraint.ThrowConstraintException();\r
+  \r
+                                               // assert all constraints\r
+                                               foreach (Constraint constraint in Constraints) {\r
+                                                       constraint.AssertConstraint();\r
+                                               }\r
+                                       }\r
+                                       enforceConstraints = value;\r
+                               }\r
+                       }\r
+               }\r
+  \r
+               internal bool RowsExist(DataColumn[] columns, DataColumn[] relatedColumns,DataRow row)\r
+               {\r
+                       int curIndex = row.IndexFromVersion(DataRowVersion.Default);\r
+                       int tmpRecord = RecordCache.NewRecord();\r
+  \r
+                       try {\r
+                               for (int i = 0; i < relatedColumns.Length; i++) {\r
+                                       // according to MSDN: the DataType value for both columns must be identical.\r
+                                       columns[i].DataContainer.CopyValue(relatedColumns[i].DataContainer, curIndex, tmpRecord);\r
+                               }\r
+                               return RowsExist(columns, tmpRecord);\r
+                       }\r
+                       finally {\r
+                               RecordCache.DisposeRecord(tmpRecord);\r
+                       }\r
+               }\r
+  \r
+               bool RowsExist(DataColumn[] columns, int index)\r
+               {\r
+                       bool rowsExist = false;\r
+                       Index indx = this.FindIndex(columns);\r
+  \r
+                       if (indx != null) { // lookup for a row in index                        \r
+                               rowsExist = (indx.Find(index) != -1);\r
+                       } \r
+                       else { \r
+                               // we have to perform full-table scan\r
+                               // check that there is a parent for this row.\r
+                               foreach (DataRow thisRow in this.Rows) {\r
+                                       if (thisRow.RowState != DataRowState.Deleted) {\r
+                                               bool match = true;\r
+                                               // check if the values in the columns are equal\r
+                                               int thisIndex = thisRow.IndexFromVersion(DataRowVersion.Current);\r
+                                               foreach (DataColumn column in columns) {\r
+                                                       if (column.DataContainer.CompareValues(thisIndex, index) != 0) {\r
+                                                               match = false;\r
+                                                               break;\r
+                                                       }       \r
+                                               }\r
+                                               if (match) {// there is a row with columns values equals to those supplied.\r
+                                                       rowsExist = true;\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                               }                               \r
+                       }\r
+                       return rowsExist;\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Commits all the changes made to this table since the \r
+               /// last time AcceptChanges was called.\r
+               /// </summary>\r
+               public void AcceptChanges () \r
+               {\r
+                       //FIXME: Do we need to validate anything here or\r
+                       //try to catch any errors to deal with them?\r
+                       \r
+                       // we do not use foreach because if one of the rows is in Delete state\r
+                       // it will be romeved from Rows and we get an exception.\r
+                       DataRow myRow;\r
+                       for (int i = 0; i < Rows.Count; )\r
+                       {\r
+                               myRow = Rows[i];\r
+                               myRow.AcceptChanges();\r
+  \r
+                               // if the row state is Detached it meens that it was removed from row list (Rows)\r
+                               // so we should not increase 'i'.\r
+                               if (myRow.RowState != DataRowState.Detached)\r
+                                       i++;\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Begins the initialization of a DataTable that is used \r
+               /// on a form or used by another component. The initialization\r
+               /// occurs at runtime.\r
+               /// </summary>\r
+               public virtual void BeginInit () \r
+               {\r
+                       fInitInProgress = true;\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Turns off notifications, index maintenance, and \r
+               /// constraints while loading data.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               public void BeginLoadData () \r
+               {\r
+                       if (!this._duringDataLoad)\r
+                       {\r
+                               //duringDataLoad is important to EndLoadData and\r
+                               //for not throwing unexpected exceptions.\r
+                               this._duringDataLoad = true;\r
+                               this._nullConstraintViolationDuringDataLoad = false;\r
+                       \r
+                               if (this.dataSet != null)\r
+                               {\r
+                                       //Saving old Enforce constraints state for later\r
+                                       //use in the EndLoadData.\r
+                                       this.dataSetPrevEnforceConstraints = this.dataSet.EnforceConstraints;\r
+                                       this.dataSet.EnforceConstraints = false;\r
+                               }\r
+                               else {\r
+                                       //if table does not belong to any data set use EnforceConstraints of the table\r
+                                       this.EnforceConstraints = false;\r
+                               }\r
+                       }\r
+                       return;\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Clears the DataTable of all data.\r
+               /// </summary>\r
+               public void Clear () {\r
+                          // Foriegn key constraints are checked in _rows.Clear method\r
+                       _rows.Clear ();\r
+++#if NET_2_0\r
+++                        OnTableCleared (new DataTableClearEventArgs (this));\r
+++#endif // NET_2_0\r
+++\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Clones the structure of the DataTable, including\r
+               ///  all DataTable schemas and constraints.\r
+               /// </summary>\r
+               public virtual DataTable Clone () \r
+               {\r
+                        // Use Activator so we can use non-public constructors.\r
+                       DataTable Copy = (DataTable) Activator.CreateInstance(GetType(), true);                 \r
+                       CopyProperties (Copy);\r
+                       return Copy;\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Computes the given expression on the current_rows that \r
+               /// pass the filter criteria.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               public object Compute (string expression, string filter) \r
+               {\r
+                       // expression is an aggregate function\r
+                       // filter is an expression used to limit rows\r
+  \r
+                       DataRow[] rows = Select(filter);\r
+                       \r
+                       if (rows == null || rows.Length == 0)\r
+                               return DBNull.Value;\r
+                       \r
+                       Parser parser = new Parser (rows);\r
+                       IExpression expr = parser.Compile (expression);\r
+                       object obj = expr.Eval (rows[0]);\r
+                       \r
+                       return obj;\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Copies both the structure and data for this DataTable.\r
+               /// </summary>\r
+               public DataTable Copy () \r
+               {\r
+                       DataTable copy = Clone();\r
+  \r
+                       copy._duringDataLoad = true;\r
+                       foreach (DataRow row in Rows) {\r
+                               DataRow newRow = copy.NewNotInitializedRow();\r
+                               copy.Rows.AddInternal(newRow);\r
+                               CopyRow(row,newRow);\r
+                       }\r
+                       copy._duringDataLoad = false;           \r
+               \r
+                       // rebuild copy indexes after loading all rows\r
+                       copy.ResetIndexes();\r
+                       return copy;\r
+               }\r
+  \r
+               internal void CopyRow(DataRow fromRow,DataRow toRow)\r
+               {\r
+                       if (fromRow.HasErrors) {\r
+                               fromRow.CopyErrors(toRow);\r
+                       }\r
+  \r
+                       if (fromRow.HasVersion(DataRowVersion.Original)) {\r
+                               toRow.Original = toRow.Table.RecordCache.CopyRecord(this,fromRow.Original,-1);\r
+                       }\r
+  \r
+                       if (fromRow.HasVersion(DataRowVersion.Current)) {\r
+                               if (fromRow.Original != fromRow.Current) {\r
+                                       toRow.Current = toRow.Table.RecordCache.CopyRecord(this,fromRow.Current,-1);\r
+                               }\r
+                               else {\r
+                                       toRow.Current = toRow.Original;\r
+                               }\r
+                       }\r
+               }\r
+  \r
+               private void CopyProperties (DataTable Copy) \r
+               {\r
+                       Copy.CaseSensitive = CaseSensitive;\r
+                       Copy._virginCaseSensitive = _virginCaseSensitive;\r
+  \r
+                       // Copy.ChildRelations\r
+                       // Copy.Constraints\r
+                       // Copy.Container\r
+                       // Copy.DefaultView\r
+                       // Copy.DesignMode\r
+                       Copy.DisplayExpression = DisplayExpression;\r
+                       if(ExtendedProperties.Count > 0) {\r
+                               //  Cannot copy extended properties directly as the property does not have a set accessor\r
+                               Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);\r
+                               ExtendedProperties.Keys.CopyTo (tgtArray, 0);\r
+                               for (int i=0; i < ExtendedProperties.Count; i++)\r
+                                       Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);\r
+                       }\r
+                       Copy.Locale = Locale;\r
+                       Copy.MinimumCapacity = MinimumCapacity;\r
+                       Copy.Namespace = Namespace;\r
+                       // Copy.ParentRelations\r
+                       Copy.Prefix = Prefix;\r
+                       Copy.Site = Site;\r
+                       Copy.TableName = TableName;\r
+  \r
+                       bool isEmpty = Copy.Columns.Count == 0;\r
+  \r
+                       // Copy columns\r
+                       foreach (DataColumn column in Columns) {                        \r
+                               // When cloning a table, the columns may be added in the default constructor.\r
+                               if (isEmpty || !Copy.Columns.Contains(column.ColumnName)) {\r
+                                       Copy.Columns.Add (column.Clone());      \r
+                               }\r
+                       }\r
+  \r
+                       CopyConstraints(Copy);\r
+                       // add primary key to the copy\r
+                       if (PrimaryKey.Length > 0) {\r
+                               DataColumn[] pColumns = new DataColumn[PrimaryKey.Length];\r
+                               for (int i = 0; i < pColumns.Length; i++)\r
+                                       pColumns[i] = Copy.Columns[PrimaryKey[i].ColumnName];\r
+  \r
+                               Copy.PrimaryKey = pColumns;\r
+                       }\r
+               }\r
+  \r
+               private void CopyConstraints(DataTable copy)\r
+               {\r
+                       UniqueConstraint origUc;\r
+                       UniqueConstraint copyUc;\r
+                       for (int i = 0; i < this.Constraints.Count; i++)\r
+                       {\r
+                               if (this.Constraints[i] is UniqueConstraint)\r
+                               {\r
+                                       origUc = (UniqueConstraint)this.Constraints[i];\r
+                                       DataColumn[] columns = new DataColumn[origUc.Columns.Length];\r
+                                       for (int j = 0; j < columns.Length; j++)\r
+                                               columns[j] = copy.Columns[origUc.Columns[j].ColumnName];\r
+                                       \r
+                                       copyUc = new UniqueConstraint(origUc.ConstraintName, columns, origUc.IsPrimaryKey);\r
+                                       copy.Constraints.Add(copyUc);\r
+                               }\r
+                       }\r
+               }\r
+               /// <summary>\r
+               /// Ends the initialization of a DataTable that is used \r
+               /// on a form or used by another component. The \r
+               /// initialization occurs at runtime.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               public virtual void EndInit () \r
+               {\r
+                       fInitInProgress = false;\r
+                       // Add the constraints\r
+                       _constraintCollection.PostEndInit();\r
+                       Columns.PostEndInit();\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Turns on notifications, index maintenance, and \r
+               /// constraints after loading data.\r
+               /// </summary>\r
+               public void EndLoadData() \r
+               {\r
+                       if (this._duringDataLoad) {\r
+                               if(this._nullConstraintViolationDuringDataLoad) {\r
+                                       this._nullConstraintViolationDuringDataLoad = false;\r
+                                       throw new ConstraintException ("Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.");\r
+                               }\r
+                               \r
+                               if (this.dataSet !=null) {\r
+                                       //Getting back to previous EnforceConstraint state\r
+                                       this.dataSet.InternalEnforceConstraints(this.dataSetPrevEnforceConstraints,true);\r
+                               }\r
+                               else {\r
+                                       //Getting back to the table's previous EnforceConstraint state\r
+                                       this.EnforceConstraints = true;\r
+                               }\r
+  \r
+                               //Returning from loading mode, raising exceptions as usual\r
+                               this._duringDataLoad = false;\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets a copy of the DataTable that contains all\r
+               ///  changes made to it since it was loaded or \r
+               ///  AcceptChanges was last called.\r
+               /// </summary>\r
+               public DataTable GetChanges() \r
+               {\r
+                       return GetChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets a copy of the DataTable containing all \r
+               /// changes made to it since it was last loaded, or \r
+               /// since AcceptChanges was called, filtered by DataRowState.\r
+               /// </summary>\r
+               public DataTable GetChanges(DataRowState rowStates) \r
+               {\r
+                       DataTable copyTable = null;\r
+  \r
+                       IEnumerator rowEnumerator = Rows.GetEnumerator();\r
+                       while (rowEnumerator.MoveNext()) {\r
+                               DataRow row = (DataRow)rowEnumerator.Current;\r
+                               // The spec says relationship constraints may cause Unchanged parent rows to be included but\r
+                               // MS .NET 1.1 does not include Unchanged rows even if their child rows are changed.\r
+                               if (row.IsRowChanged(rowStates)) {\r
+                                       if (copyTable == null)\r
+                                               copyTable = Clone();\r
+                                       DataRow newRow = copyTable.NewNotInitializedRow();\r
+                                       row.CopyValuesToRow(newRow);\r
+                                       copyTable.Rows.AddInternal (newRow);\r
+                               }\r
+                       }\r
+                        \r
+                       return copyTable;\r
+               }\r
+  \r
+  #if NET_2_0\r
+               [MonoTODO]\r
+               public DataTableReader GetDataReader ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+  #endif\r
+  \r
+               /// <summary>\r
+               /// Gets an array of DataRow objects that contain errors.\r
+               /// </summary>\r
+               public DataRow[] GetErrors () \r
+               {\r
+                       ArrayList errors = new ArrayList();\r
+                       for (int i = 0; i < _rows.Count; i++)\r
+                       {\r
+                               if (_rows[i].HasErrors)\r
+                                       errors.Add(_rows[i]);\r
+                       }\r
+                       \r
+                       DataRow[] ret = NewRowArray(errors.Count);\r
+                       errors.CopyTo(ret, 0);\r
+                       return ret;\r
+               }\r
+       \r
+               /// <summary>\r
+               /// This member is only meant to support Mono's infrastructure \r
+               /// </summary>\r
+               protected virtual DataTable CreateInstance () \r
+               {\r
+                       return Activator.CreateInstance (this.GetType (), true) as DataTable;\r
+               }\r
+  \r
+               /// <summary>\r
+               /// This member is only meant to support Mono's infrastructure \r
+               /// </summary>\r
+               protected virtual Type GetRowType () \r
+               {\r
+                       return typeof (DataRow);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// This member is only meant to support Mono's infrastructure \r
+               /// \r
+               /// Used for Data Binding between System.Web.UI. controls \r
+               /// like a DataGrid\r
+               /// or\r
+               /// System.Windows.Forms controls like a DataGrid\r
+               /// </summary>\r
+               IList IListSource.GetList () \r
+               {\r
+                       IList list = (IList) DefaultView;\r
+                       return list;\r
+               }\r
+                               \r
+               /// <summary>\r
+               /// Copies a DataRow into a DataTable, preserving any \r
+               /// property settings, as well as original and current values.\r
+               /// </summary>\r
+               public void ImportRow (DataRow row) \r
+               {\r
+                       DataRow newRow = NewNotInitializedRow();\r
 --                     \r
+++\r
+++                     int original = -1;\r
+                       if (row.HasVersion(DataRowVersion.Original)) {\r
 --                             if (!newRow.HasVersion(DataRowVersion.Original)) {\r
 --                                     newRow.Original = RecordCache.NewRecord();\r
 --                             }                               \r
 --                             int original = row.IndexFromVersion(DataRowVersion.Original);\r
+++                             original = row.IndexFromVersion(DataRowVersion.Original);\r
+++                             newRow.Original = RecordCache.NewRecord();\r
+                               RecordCache.CopyRecord(row.Table,original,newRow.Original);\r
+                       }\r
+  \r
+                       if (row.HasVersion(DataRowVersion.Current)) {\r
 --                             if (!newRow.HasVersion(DataRowVersion.Current)) {\r
 --                                     newRow.Current = RecordCache.NewRecord();\r
 --                             }                               \r
+                               int current = row.IndexFromVersion(DataRowVersion.Current);\r
 --                             RecordCache.CopyRecord(row.Table,current,newRow.Current);\r
+++                             if (current == original)\r
+++                                     newRow.Current = newRow.Original;\r
+++                             else {\r
+++                                     newRow.Current = RecordCache.NewRecord();\r
+++                                     RecordCache.CopyRecord(row.Table,current,newRow.Current);\r
+++                             }\r
+                       }\r
+  \r
++                      if (EnforceConstraints)\r
++                              // we have to check that the new row doesn't colide with existing row\r
++                              Rows.ValidateDataRowInternal(newRow);\r
++ \r
+                       Rows.AddInternal(newRow);               \r
+       \r
+                       if (row.HasErrors) {\r
+                               row.CopyErrors(newRow);\r
+                       }\r
+               }\r
+  \r
+               internal int DefaultValuesRowIndex\r
+               {\r
+                       get {\r
+                               return _defaultValuesRowIndex;\r
+                       }       \r
+               }\r
+  \r
+               /// <summary>\r
+               /// This member is only meant to support Mono's infrastructure          \r
+               /// </summary>\r
+               void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) \r
+               {\r
+                       DataSet dset;\r
+                       if (dataSet != null)\r
+                               dset = dataSet;\r
+                       else {\r
+                               dset = new DataSet ("tmpDataSet");\r
+                               dset.Tables.Add (this);\r
+                       }\r
+                       \r
+                       StringWriter sw = new StringWriter ();\r
+                       XmlTextWriter tw = new XmlTextWriter (sw);\r
+                       tw.Formatting = Formatting.Indented;\r
+                       dset.WriteIndividualTableContent (tw, this, XmlWriteMode.DiffGram);\r
+                       tw.Close ();\r
+                       \r
+                       StringWriter sw2 = new StringWriter ();\r
+                       DataTableCollection tables = new DataTableCollection (dset);\r
+                       tables.Add (this);\r
+                       XmlSchemaWriter.WriteXmlSchema (dset, new XmlTextWriter (sw2), tables, null);\r
+                       sw2.Close ();\r
+                       \r
+                       info.AddValue ("XmlSchema", sw2.ToString(), typeof(string));\r
+                       info.AddValue ("XmlDiffGram", sw.ToString(), typeof(string));\r
+               }\r
+  \r
+  #if NET_2_0\r
 --             [MonoTODO]\r
+++                /// <summary>\r
+++                ///     Loads the table with the values from the reader\r
+++                /// </summary>\r
+               public void Load (IDataReader reader)\r
+               {\r
 --                     throw new NotImplementedException ();\r
+++                        Load (reader, LoadOption.PreserveChanges);\r
+               }\r
+  \r
 --             [MonoTODO]\r
+++                /// <summary>\r
+++                ///     Loads the table with the values from the reader and the pattern\r
+++                ///     of the changes to the existing rows or the new rows are based on\r
+++                ///     the LoadOption passed.\r
+++                /// </summary>\r
+               public void Load (IDataReader reader, LoadOption loadOption)\r
+               {\r
 --                     throw new NotImplementedException ();\r
 --             }\r
+++                        bool prevEnforceConstr = this.EnforceConstraints;\r
+++                        try {\r
+++                                this.EnforceConstraints = false;\r
+++                                int [] mapping = DbDataAdapter.BuildSchema (reader, this, SchemaType.Mapped, \r
+++                                                                            MissingSchemaAction.AddWithKey,\r
+++                                                                            MissingMappingAction.Passthrough, \r
+++                                                                            new DataTableMappingCollection ());\r
+++                                DbDataAdapter.FillFromReader (this,\r
+++                                                              reader,\r
+++                                                              0, // start from\r
+++                                                              0, // all records\r
+++                                                              mapping,\r
+++                                                              loadOption);\r
+++                        } finally {\r
+++                                this.EnforceConstraints = prevEnforceConstr;\r
+++                        }\r
+++             }\r
+++\r
+++                \r
+  #endif\r
+  \r
+               /// <summary>\r
+               /// Finds and updates a specific row. If no matching row\r
+               ///  is found, a new row is created using the given values.\r
+               /// </summary>\r
+               public DataRow LoadDataRow (object[] values, bool fAcceptChanges) \r
+               {\r
+                       DataRow row = null;\r
+                       if (PrimaryKey.Length == 0) {\r
+                               row = Rows.Add (values);\r
+                               if (fAcceptChanges)\r
+                                       row.AcceptChanges ();\r
+                       }\r
+                       else {\r
+                               int newRecord = CreateRecord(values);\r
+                               int existingRecord = _primaryKeyConstraint.Index.Find(newRecord);\r
+  \r
+                               if (existingRecord < 0) {\r
+                                       row = NewRowFromBuilder (RowBuilder);\r
+                                       row.Proposed = newRecord;\r
+                                       Rows.AddInternal(row);\r
+                               }\r
+                               else {\r
+                                       row = RecordCache[existingRecord];\r
+                                       row.BeginEdit();\r
+                                       row.ImportRecord(newRecord);\r
+                                       row.EndEdit();\r
+                                       \r
+                               }\r
+                               \r
+                               if (fAcceptChanges)\r
+                                       row.AcceptChanges ();\r
+                       }\r
+                               \r
+                       return row;\r
+               }\r
+  \r
+               internal DataRow LoadDataRow(IDataRecord record, int[] mapping, int length, bool fAcceptChanges)\r
+               {\r
+                       DataRow row = null;\r
+                               int tmpRecord = this.RecordCache.NewRecord();\r
+                               try {\r
+                               RecordCache.ReadIDataRecord(tmpRecord,record,mapping,length);\r
+                               if (PrimaryKey.Length != 0) {\r
+                                       bool hasPrimaryValues = true;\r
+                                       foreach(DataColumn col in PrimaryKey) {\r
+                                               if(!(col.Ordinal < mapping.Length)) {\r
+                                                       hasPrimaryValues = false;\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                                       \r
+                                       if (hasPrimaryValues) {\r
+                                               // find the row in the table.\r
+                                               row = Rows.Find(tmpRecord);\r
+                                       }\r
+                               }\r
+                                       \r
+                               bool shouldUpdateIndex = false;\r
+                               if (row == null) {\r
+                                       row = NewNotInitializedRow();\r
+                                       row.ImportRecord(tmpRecord);\r
+                                       Rows.AddInternal (row);\r
+                                       shouldUpdateIndex = true;\r
+                               }\r
+                               else {\r
+                                       // Proposed = tmpRecord\r
+                                       row.ImportRecord(tmpRecord);\r
+                               }\r
+                               \r
+                               if (fAcceptChanges) {\r
+                                       row.AcceptChanges();\r
+                               }\r
+                               \r
+                               if (shouldUpdateIndex || !fAcceptChanges) {\r
+                                       // AcceptChanges not always updates indexes because it calls EndEdit\r
+                                       foreach(Index index in Indexes) {\r
+                                               index.Update(row,tmpRecord);\r
+                                       }\r
+                               }\r
+  \r
+                       }\r
+                       catch(Exception e) {\r
+                               this.RecordCache.DisposeRecord(tmpRecord);\r
+                               throw e;\r
+                       }                               \r
+                       return row;\r
+               }\r
+  \r
+  #if NET_2_0\r
 --             [MonoTODO]\r
 --             public DataRow LoadDataRow (object[] values, LoadOption loadOption)\r
 --             {\r
 --                     throw new NotImplementedException ();\r
+++                /// <summary>\r
+++                ///     Loads the given values into an existing row if matches or creates\r
+++                ///     the new row popluated with the values.\r
+++                /// </summary>\r
+++                /// <remarks>\r
+++                ///     This method searches for the values using primary keys and it first\r
+++                ///     searches using the original values of the rows and if not found, it\r
+++                ///     searches using the current version of the row.\r
+++                /// </remarks>\r
+++             public DataRow LoadDataRow (object [] values, LoadOption loadOption)\r
+++             {\r
+++                        DataRow row  = null;\r
+++                        bool new_row = false;\r
+++                        \r
+++                        // Find Data DataRow\r
+++                        if (this.PrimaryKey.Length > 0) {\r
+++                                object [] keyValues = new object [this.PrimaryKey.Length];\r
+++                                for (int i = 0; i < keyValues.Length; i++)\r
+++                                        keyValues [i] = values [this.PrimaryKey [i].Ordinal];\r
+++                                row = this.Rows.Find (keyValues, DataRowVersion.Original );\r
+++                                if (row == null) \r
+++                                        row = this.Rows.Find (keyValues, DataRowVersion.Current);\r
+++                        }\r
+++                                \r
+++                        // If not found, add new row\r
+++                        if (row == null) {\r
+++                                row = this.NewRow ();\r
+++                                new_row = true;\r
+++                        }\r
+++\r
+++                        bool deleted = row.RowState == DataRowState.Deleted;\r
+++\r
+++                        if (deleted && loadOption == LoadOption.OverwriteChanges)\r
+++                                row.RejectChanges ();                        \r
+++\r
+++                        row.Load (values, loadOption, new_row);\r
+++\r
+++                        if (deleted && loadOption == LoadOption.Upsert) {\r
+++                                row = this.NewRow ();\r
+++                                row.Load (values, loadOption, new_row = true);\r
+++                        }\r
+++\r
+++                        if (new_row) {\r
+++                                this.Rows.Add (row);\r
+++                                if (loadOption == LoadOption.OverwriteChanges ||\r
+++                                    loadOption == LoadOption.PreserveChanges) {\r
+++                                        row.AcceptChanges ();\r
+++                                }\r
+++                        }\r
+++\r
+++                        return row;\r
+               }\r
+  \r
+               [MonoTODO]\r
+               public void Merge (DataTable table)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+  \r
+               [MonoTODO]\r
+               public void Merge (DataTable table, bool preserveChanges)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+  \r
+               [MonoTODO]\r
+               public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+  #endif\r
+  \r
+               /// <summary>\r
+               /// Creates a new DataRow with the same schema as the table.\r
+               /// </summary>\r
+               public DataRow NewRow () \r
+               {\r
+                       EnsureDefaultValueRowIndex();\r
+  \r
+                       DataRow newRow = NewRowFromBuilder (RowBuilder);\r
+  \r
+                       newRow.Proposed = CreateRecord(null);\r
+                       return newRow;\r
+               }\r
+  \r
+               internal int CreateRecord(object[] values) {\r
+                       int valCount = values != null ? values.Length : 0;\r
+                       if (valCount > Columns.Count)\r
+                               throw new ArgumentException("Input array is longer than the number of columns in this table.");\r
+  \r
+                       int index = RecordCache.NewRecord();\r
+  \r
+                       try {\r
+                               for (int i = 0; i < valCount; i++) {\r
+                                       try {\r
+                                               Columns[i].DataContainer[index] = values[i];\r
+                                       }\r
+                                       catch(Exception e) {\r
+                                               throw new ArgumentException(e.Message +\r
+                                                       String.Format("Couldn't store <{0}> in {1} Column.  Expected type is {2}.",\r
+                                                       values[i], Columns[i].ColumnName, Columns[i].DataType.Name), e);\r
+                                       }\r
+                               }\r
+  \r
+                               for(int i = valCount; i < Columns.Count; i++) {\r
+                                       DataColumn column = Columns[i];\r
+                                       if (column.AutoIncrement)\r
+                                               column.DataContainer[index] = column.AutoIncrementValue ();\r
+                                       else\r
+                                               column.DataContainer.CopyValue(DefaultValuesRowIndex, index);\r
+                               }\r
+  \r
+                               return index;\r
+                       }\r
+                       catch {\r
+                               RecordCache.DisposeRecord(index);\r
+                               throw;\r
+                       }\r
+               }\r
+  \r
+               private void EnsureDefaultValueRowIndex()\r
+               {\r
+                       // initialize default values row for the first time\r
+                       if ( _defaultValuesRowIndex == -1 ) {\r
+                               _defaultValuesRowIndex = RecordCache.NewRecord();\r
+                               foreach(DataColumn column in Columns) {\r
+                                       column.DataContainer[_defaultValuesRowIndex] = column.DefaultValue;\r
+                               }\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// This member supports the .NET Framework infrastructure\r
+               ///  and is not intended to be used directly from your code.\r
+               /// </summary>\r
+               protected internal DataRow[] NewRowArray (int size) \r
+               {\r
+                       return (DataRow[]) Array.CreateInstance (GetRowType (), size);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Creates a new row from an existing row.\r
+               /// </summary>\r
+               protected virtual DataRow NewRowFromBuilder (DataRowBuilder builder) \r
+               {\r
+                       return new DataRow (builder);\r
+               }\r
+               \r
+               internal DataRow NewNotInitializedRow()\r
+               {\r
+                       EnsureDefaultValueRowIndex();\r
+  \r
+                       return NewRowFromBuilder (RowBuilder);\r
+               }\r
+  \r
+  #if NET_2_0\r
+               [MonoTODO]\r
+               XmlReadMode ReadXml (Stream stream)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+  \r
+               public void ReadXmlSchema (Stream stream)\r
+               {\r
+                       ReadXmlSchema (new XmlTextReader (stream));\r
+               }\r
+  \r
+               public void ReadXmlSchema (TextReader reader)\r
+               {\r
+                       ReadXmlSchema (new XmlTextReader (reader));\r
+               }\r
+  \r
+               public void ReadXmlSchema (string fileName)\r
+               {\r
+                       XmlTextReader reader = null;\r
+                       try {\r
+                               reader = new XmlTextReader (fileName);\r
+                       ReadXmlSchema (reader);\r
+                       } finally {\r
+                               if (reader != null)\r
+                       reader.Close ();\r
+               }\r
+               }\r
+  \r
+               public void ReadXmlSchema (XmlReader reader)\r
+               {\r
+                       DataSet ds = new DataSet ();\r
+                       new XmlSchemaDataImporter (ds, reader).Process ();\r
+                       DataTable target = null;\r
+                       if (TableName == String.Empty) {\r
+                               if (ds.Tables.Count > 0)\r
+                                       target = ds.Tables [0];\r
+                       }\r
+                       else {\r
+                               target = ds.Tables [TableName];\r
+                               if (target == null)\r
+                                       throw new ArgumentException (String.Format ("DataTable '{0}' does not match to any DataTable in source.", TableName));\r
+                       }\r
+                       if (target != null)\r
+                               target.CopyProperties (this);\r
+               }\r
+  #endif\r
+  \r
+               /// <summary>\r
+               /// Rolls back all changes that have been made to the \r
+               /// table since it was loaded, or the last time AcceptChanges\r
+               ///  was called.\r
+               /// </summary>\r
+               public void RejectChanges () \r
+               {       \r
+                       for (int i = _rows.Count - 1; i >= 0; i--) {\r
+                               DataRow row = _rows [i];\r
+                               if (row.RowState != DataRowState.Unchanged)\r
+                                       _rows [i].RejectChanges ();\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Resets the DataTable to its original state.\r
+               /// </summary>          \r
+               public virtual void Reset () \r
+               {\r
+                       Clear();\r
+                       while (ParentRelations.Count > 0)\r
+                       {\r
+                               if (dataSet.Relations.Contains(ParentRelations[ParentRelations.Count - 1].RelationName))\r
+                                       dataSet.Relations.Remove(ParentRelations[ParentRelations.Count - 1]);\r
+                       }\r
+  \r
+                       while (ChildRelations.Count > 0)\r
+                       {\r
+                               if (dataSet.Relations.Contains(ChildRelations[ChildRelations.Count - 1].RelationName))\r
+                                       dataSet.Relations.Remove(ChildRelations[ChildRelations.Count - 1]);\r
+                       }\r
+                       Constraints.Clear();\r
+                       Columns.Clear();\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets an array of all DataRow objects.\r
+               /// </summary>\r
+               public DataRow[] Select () \r
+               {\r
+                       return Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets an array of all DataRow objects that match \r
+               /// the filter criteria in order of primary key (or \r
+               /// lacking one, order of addition.)\r
+               /// </summary>\r
+               public DataRow[] Select (string filterExpression) \r
+               {\r
+                       return Select(filterExpression, String.Empty, DataViewRowState.CurrentRows);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets an array of all DataRow objects that \r
+               /// match the filter criteria, in the the \r
+               /// specified sort order.\r
+               /// </summary>\r
+               public DataRow[] Select (string filterExpression, string sort) \r
+               {\r
+                       return Select(filterExpression, sort, DataViewRowState.CurrentRows);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets an array of all DataRow objects that match\r
+               /// the filter in the order of the sort, that match \r
+               /// the specified state.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               public DataRow[] Select(string filterExpression, string sort, DataViewRowState recordStates) \r
+               {\r
+                       if (filterExpression == null)\r
+                               filterExpression = String.Empty;\r
+  \r
+                       DataColumn[] columns = _emptyColumnArray;\r
+                       ListSortDirection[] sorts = null;\r
+                       if (sort != null && !sort.Equals(String.Empty))\r
+                               columns = ParseSortString (this, sort, out sorts, false);\r
+  \r
+                       IExpression filter = null;\r
+                       if (filterExpression != String.Empty) {\r
+                               Parser parser = new Parser ();\r
+                               filter = parser.Compile (filterExpression);\r
+                       }\r
+  \r
+                       Index index = FindIndex(columns, sorts, recordStates, filter);\r
+                       if (index == null)\r
+                               index = new Index(new Key(this,columns,sorts,recordStates,filter));\r
+  \r
+                       int[] records = index.GetAll();\r
+                       DataRow[] dataRows = NewRowArray(index.Size);\r
+                       for (int i = 0; i < dataRows.Length; i++)\r
+                               dataRows[i] = RecordCache[records[i]];\r
+  \r
+                       return dataRows;\r
+               }\r
+  \r
+               \r
+               private void AddIndex (Index index)\r
+               {\r
+                       if (_indexes == null) {\r
+                               _indexes = new ArrayList();\r
+                       }\r
+  \r
+                       _indexes.Add (index);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Returns index corresponding to columns,sort,row state filter and unique values given.\r
+               /// If such an index not exists, creates a new one.\r
+               /// </summary>\r
+               /// <param name="columns">Columns set of the index to look for.</param>\r
+               /// <param name="sort">Columns sort order of the index to look for.</param>\r
+               /// <param name="rowState">Rpw state filter of the index to look for.</param>\r
+               /// <param name="unique">Uniqueness of the index to look for.</param>\r
+               /// <param name="strict">Indicates whenever the index found should correspond in its uniquness to the value of unique parameter specified.</param>\r
+               /// <param name="reset">Indicates whenever the already existing index should be forced to reset.</param>\r
+               /// <returns></returns>\r
+               internal Index GetIndex(DataColumn[] columns, ListSortDirection[] sort, DataViewRowState rowState, IExpression filter, bool reset)\r
+               {\r
+                       Index index = FindIndex(columns,sort,rowState,filter);\r
+                       if (index == null ) {\r
+                               index = new Index(new Key(this,columns,sort,rowState,filter));\r
+  \r
+                               AddIndex(index);\r
+                       }\r
+                       else if (reset) {\r
+                               // reset existing index only if asked for this\r
+                               index.Reset();\r
+                       }\r
+                       return index;\r
+               }\r
+  \r
+               internal Index FindIndex(DataColumn[] columns)\r
+               {\r
+                       return FindIndex(columns,null,DataViewRowState.None, null);\r
+               }\r
+  \r
+               internal Index FindIndex(DataColumn[] columns, ListSortDirection[] sort, DataViewRowState rowState, IExpression filter)\r
+               {\r
+                       if (Indexes != null) {\r
+                               foreach (Index index in Indexes) {\r
+                                       if (index.Key.Equals(columns,sort,rowState, filter)) {\r
+                                               return index;\r
+                                       }\r
+                               }\r
+                       }\r
+                       return null;\r
+               }\r
+  \r
+               internal void ResetIndexes()\r
+               {\r
+                       foreach(Index index in Indexes) {\r
+                               index.Reset();\r
+                       }\r
+               }\r
+  \r
+               internal void ResetCaseSensitiveIndexes()\r
+               {\r
+                       foreach(Index index in Indexes) {\r
+                               bool containsStringcolumns = false;\r
+                               foreach(DataColumn column in index.Key.Columns) {\r
+                                       if (column.DataType == typeof(string)) {\r
+                                               containsStringcolumns = true;\r
+                                               break;\r
+                                       }\r
+                               }\r
+  \r
+                               if (containsStringcolumns) {\r
+                                       index.Reset();\r
+                               }\r
+                       }\r
+               }\r
+  \r
+               internal void DropIndex(Index index)\r
+               {\r
+                       if (index != null && index.RefCount == 0) {     \r
+                               _indexes.Remove(index);\r
+                       }\r
+               }\r
+  \r
+               internal void DeleteRowFromIndexes (DataRow row)\r
+               {\r
+                       if (_indexes != null) {\r
+                               foreach (Index indx in _indexes) {\r
+                                       indx.Delete (row);\r
+                               }\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Gets the TableName and DisplayExpression, if \r
+               /// there is one as a concatenated string.\r
+               /// </summary>\r
+               public override string ToString() \r
+               {\r
+                       //LAMESPEC: spec says concat the two. impl puts a \r
+                       //plus sign infront of DisplayExpression\r
+                       string retVal = TableName;\r
+                       if(DisplayExpression != null && DisplayExpression != "")\r
+                               retVal += " + " + DisplayExpression;\r
+                       return retVal;\r
+               }\r
+  \r
+  #if NET_2_0\r
+               private XmlWriterSettings GetWriterSettings ()\r
+               {\r
+                       XmlWriterSettings s = new XmlWriterSettings ();\r
+                       s.Indent = true;\r
+                       return s;\r
+               }\r
+  \r
+               public void WriteXml (Stream stream)\r
+               {\r
+                       WriteXml (stream, XmlWriteMode.IgnoreSchema);\r
+               }\r
+  \r
+               public void WriteXml (TextWriter writer)\r
+               {\r
+                       WriteXml (writer, XmlWriteMode.IgnoreSchema);\r
+               }\r
+  \r
+               public void WriteXml (XmlWriter writer)\r
+               {\r
+                       WriteXml (writer, XmlWriteMode.IgnoreSchema);\r
+               }\r
+  \r
+               public void WriteXml (string fileName)\r
+               {\r
+                       WriteXml (fileName, XmlWriteMode.IgnoreSchema);\r
+               }\r
+  \r
+               public void WriteXml (Stream stream, XmlWriteMode mode)\r
+               {\r
+                       WriteXml (XmlWriter.Create (stream, GetWriterSettings ()), mode);\r
+               }\r
+  \r
+               public void WriteXml (TextWriter writer, XmlWriteMode mode)\r
+               {\r
+                       WriteXml (XmlWriter.Create (writer, GetWriterSettings ()), mode);\r
+               }\r
+  \r
+               [MonoTODO]\r
+               public void WriteXml (XmlWriter writer, XmlWriteMode mode)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+  \r
+               public void WriteXml (string fileName, XmlWriteMode mode)\r
+               {\r
+                       XmlWriter xw = null;\r
+                       try {\r
+                               xw = XmlWriter.Create (fileName, GetWriterSettings ());\r
+                               WriteXml (xw, mode);\r
+                       } finally {\r
+                               if (xw != null)\r
+                                       xw.Close ();\r
+                       }\r
+               }\r
+  \r
+               public void WriteXmlSchema (Stream stream)\r
+               {\r
+                       WriteXmlSchema (XmlWriter.Create (stream, GetWriterSettings ()));\r
+               }\r
+  \r
+               public void WriteXmlSchema (TextWriter writer)\r
+               {\r
+                       WriteXmlSchema (XmlWriter.Create (writer, GetWriterSettings ()));\r
+               }\r
+  \r
+               public void WriteXmlSchema (XmlWriter writer)\r
+               {\r
+                       DataSet ds = DataSet;\r
+                       DataSet tmp = null;\r
+                       try {\r
+                               if (ds == null) {\r
+                                       tmp = ds = new DataSet ();\r
+                                       ds.Tables.Add (this);\r
+                               }\r
+                               DataTableCollection col = new DataTableCollection (ds);\r
+                               col.Add (this);\r
+                               XmlSchemaWriter.WriteXmlSchema (ds, writer, col, null);\r
+                       } finally {\r
+                               if (tmp != null)\r
+                                       ds.Tables.Remove (this);\r
+                       }\r
+               }\r
+  \r
+               public void WriteXmlSchema (string fileName)\r
+               {\r
+                       XmlWriter xw = null;\r
+                       try {\r
+                               xw = XmlWriter.Create (fileName, GetWriterSettings ());\r
+                               WriteXmlSchema (xw);\r
+                       } finally {\r
+                               if (xw != null)\r
+                                       xw.Close ();\r
+                       }\r
+               }\r
+  #endif\r
+               \r
+               #region Events \r
+               \r
+               /// <summary>\r
+               /// Raises the ColumnChanged event.\r
+               /// </summary>\r
+               protected virtual void OnColumnChanged (DataColumnChangeEventArgs e) {\r
+                       if (null != ColumnChanged) {\r
+                               ColumnChanged (this, e);\r
+                       }\r
+               }\r
+  \r
+               internal void RaiseOnColumnChanged (DataColumnChangeEventArgs e) {\r
+                       OnColumnChanged(e);\r
+               }\r
+  \r
+++#if NET_2_0\r
+++                /// <summary>\r
+++             /// Raises TableCleared Event and delegates to subscribers\r
+++             /// </summary>\r
+++             protected virtual void OnTableCleared (DataTableClearEventArgs e) {\r
+++                     if (TableCleared != null)\r
+++                             TableCleared (this, e);\r
+++             }\r
+++#endif // NET_2_0\r
+++\r
+               /// <summary>\r
+               /// Raises the ColumnChanging event.\r
+               /// </summary>\r
+               protected virtual void OnColumnChanging (DataColumnChangeEventArgs e) {\r
+                       if (null != ColumnChanging) {\r
+                               ColumnChanging (this, e);\r
+                       }\r
+               }\r
+  \r
+               internal void RaiseOnColumnChanging (DataColumnChangeEventArgs e) {\r
+                       OnColumnChanging(e);\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Raises the PropertyChanging event.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent) {\r
+                       //      if (null != PropertyChanging)\r
+                       //      {\r
+                       //              PropertyChanging (this, e);\r
+                       //      }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Notifies the DataTable that a DataColumn is being removed.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               protected internal virtual void OnRemoveColumn (DataColumn column) {\r
+               }\r
+  \r
+  \r
+               /// <summary>\r
+               /// Raises the RowChanged event.\r
+               /// </summary>\r
+               protected virtual void OnRowChanged (DataRowChangeEventArgs e) {\r
+                       if (null != RowChanged) {\r
+                               RowChanged(this, e);\r
+                       }\r
+               }\r
+  \r
+  \r
+               /// <summary>\r
+               /// Raises the RowChanging event.\r
+               /// </summary>\r
+               protected virtual void OnRowChanging (DataRowChangeEventArgs e) {\r
+                       if (null != RowChanging) {\r
+                               RowChanging(this, e);\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Raises the RowDeleted event.\r
+               /// </summary>\r
+               protected virtual void OnRowDeleted (DataRowChangeEventArgs e) {\r
+                       if (null != RowDeleted) {\r
+                               RowDeleted(this, e);\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Raises the RowDeleting event.\r
+               /// </summary>\r
+               protected virtual void OnRowDeleting (DataRowChangeEventArgs e) {\r
+                       if (null != RowDeleting) {\r
+                               RowDeleting(this, e);\r
+                       }\r
+               }\r
+  \r
+               /// <summary>\r
+               /// Occurs when after a value has been changed for \r
+               /// the specified DataColumn in a DataRow.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs when a value has been changed for this column.")]\r
+               public event DataColumnChangeEventHandler ColumnChanged;\r
+  \r
+               /// <summary>\r
+               /// Occurs when a value is being changed for the specified \r
+               /// DataColumn in a DataRow.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Occurs when a value has been submitted for this column. The user can modify the proposed value and should throw an exception to cancel the edit.")]\r
+               public event DataColumnChangeEventHandler ColumnChanging;\r
+  \r
+               /// <summary>\r
+               /// Occurs after a DataRow has been changed successfully.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs after a row in the table has been successfully edited.")]\r
+               public event DataRowChangeEventHandler RowChanged;\r
+  \r
+               /// <summary>\r
+               /// Occurs when a DataRow is changing.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs when the row is being changed so that the event handler can modify or cancel the change. The user can modify values in the row and should throw an  exception to cancel the edit.")]\r
+               public event DataRowChangeEventHandler RowChanging;\r
+  \r
+               /// <summary>\r
+               /// Occurs after a row in the table has been deleted.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs after a row in the table has been successfully deleted.")] \r
+               public event DataRowChangeEventHandler RowDeleted;\r
+  \r
+               /// <summary>\r
+               /// Occurs before a row in the table is about to be deleted.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs when a row in the table marked for deletion. Throw an exception to cancel the deletion.")]\r
+               public event DataRowChangeEventHandler RowDeleting;\r
 --             \r
+++\r
+++#if NET_2_0\r
+++             /// <summary>\r
+++             /// Occurs after the Clear method is called on the datatable.\r
+++             /// </summary>\r
+++             [DataCategory ("Data")] \r
+++             [DataSysDescription ("Occurs when the rows in a table is cleared . Throw an exception to cancel the deletion.")]\r
+++             public event DataTableClearEventHandler TableCleared;\r
+++#endif // NET_2_0\r
+++\r
+               #endregion // Events\r
+  \r
+               /// <summary>\r
+               ///  Removes all UniqueConstraints\r
+               /// </summary>\r
+               private void RemoveUniqueConstraints () \r
+               {\r
+                       foreach (Constraint Cons in Constraints) {\r
+                               \r
+                               if (Cons is UniqueConstraint) {\r
+                                       Constraints.Remove (Cons);\r
+                                       break;\r
+                               }\r
+                       }\r
+                       \r
+                       UniqueConstraint.SetAsPrimaryKey(this.Constraints, null);\r
+               }\r
+  \r
+               internal static DataColumn[] ParseSortString (DataTable table, string sort, out ListSortDirection[] sortDirections, bool rejectNoResult)\r
+               {\r
+                       DataColumn[] sortColumns = _emptyColumnArray;\r
+                       sortDirections = null;\r
+                       \r
+                       ArrayList columns = null;\r
+                       ArrayList sorts = null;\r
+               \r
+                       if (sort != null && !sort.Equals ("")) {\r
+                               columns = new ArrayList ();\r
+                               sorts = new ArrayList();\r
+                               string[] columnExpression = sort.Trim ().Split (new char[1] {','});\r
+                       \r
+                               for (int c = 0; c < columnExpression.Length; c++) {\r
+                                       string[] columnSortInfo = columnExpression[c].Trim ().Split (new char[1] {' '});\r
+                               \r
+                                       string columnName = columnSortInfo[0].Trim ();\r
+                                       string sortOrder = "ASC";\r
+                                       if (columnSortInfo.Length > 1) \r
+                                               sortOrder = columnSortInfo[1].Trim ().ToUpper (table.Locale);\r
+                                       \r
+                                       ListSortDirection sortDirection = ListSortDirection.Ascending;\r
+                                       switch (sortOrder) {\r
+                                       case "ASC":\r
+                                               sortDirection = ListSortDirection.Ascending;\r
+                                               break;\r
+                                       case "DESC":\r
+                                               sortDirection = ListSortDirection.Descending;\r
+                                               break;\r
+                                       default:\r
+                                               throw new IndexOutOfRangeException ("Could not find column: " + columnExpression[c]);\r
+                                       }\r
+  \r
+                                       if (columnName.StartsWith("[") || columnName.EndsWith("]")) {\r
+                                               if (columnName.StartsWith("[") && columnName.EndsWith("]"))\r
+                                                       columnName = columnName.Substring(1, columnName.Length - 2);\r
+                                               else\r
+                                                       throw new ArgumentException(String.Format("{0} isn't a valid Sort string entry.", columnName));\r
+                                       }\r
+  \r
+                                       DataColumn dc = table.Columns[columnName];\r
+                                       if (dc == null){\r
+                                               try {\r
+                                                       dc = table.Columns[Int32.Parse (columnName)];\r
+                                       }\r
+                                       catch (FormatException) {\r
+                                                       throw new IndexOutOfRangeException("Cannot find column " + columnName);\r
+                                       }\r
+                                       }\r
+  \r
+                                       columns.Add (dc);\r
+                                       sorts.Add(sortDirection);\r
+                               }       \r
+                               sortColumns = (DataColumn[]) columns.ToArray (typeof (DataColumn));\r
+                               sortDirections = new ListSortDirection[sorts.Count];\r
+                               for (int i = 0; i < sortDirections.Length; i++)\r
+                                       sortDirections[i] = (ListSortDirection)sorts[i];\r
+                       }               \r
+  \r
+                       if (rejectNoResult) {\r
+                               if (sortColumns == null)\r
+                                       throw new SystemException ("sort expression result is null");\r
+                               if (sortColumns.Length == 0)\r
+                                       throw new SystemException("sort expression result is 0");\r
+                       }\r
+  \r
+                       return sortColumns;\r
+               }\r
+  \r
+               private void UpdatePropertyDescriptorsCache()\r
+               {\r
+                       PropertyDescriptor[] descriptors = new PropertyDescriptor[Columns.Count + ChildRelations.Count];\r
+                       int index = 0;\r
+                       foreach(DataColumn col in Columns) {\r
+                               descriptors[index++] = new DataColumnPropertyDescriptor(col);\r
+                       }\r
+  \r
+                       foreach(DataRelation rel in ChildRelations) {\r
+                               descriptors[index++] = new DataRelationPropertyDescriptor(rel);\r
+                       }\r
+  \r
+                       _propertyDescriptorsCache = new PropertyDescriptorCollection(descriptors);\r
+               }\r
+  \r
+               internal PropertyDescriptorCollection GetPropertyDescriptorCollection()\r
+               {\r
+                       if (_propertyDescriptorsCache == null) {\r
+                               UpdatePropertyDescriptorsCache();\r
+                       }\r
+  \r
+                       return _propertyDescriptorsCache;\r
+               }\r
+  \r
+               internal void ResetPropertyDescriptorsCache() {\r
+                       _propertyDescriptorsCache = null;\r
+               }\r
+       }\r
+  }\r