merge -r 53370:58178
authorKonstantin Triger <kostat@mono-cvs.ximian.com>
Mon, 20 Mar 2006 13:31:41 +0000 (13:31 -0000)
committerKonstantin Triger <kostat@mono-cvs.ximian.com>
Mon, 20 Mar 2006 13:31:41 +0000 (13:31 -0000)
svn path=/branches/mainsoft/gh1.7/mcs/; revision=58179

1  2 
mcs/class/System.Data/System.Data/ChangeLog
mcs/class/System.Data/System.Data/ConstraintCollection.cs
mcs/class/System.Data/System.Data/DataSet.cs
mcs/class/System.Data/System.Data/MergeManager.cs
mcs/class/System.Data/Test/System.Data/ChangeLog
mcs/class/System.Data/Test/System.Data/ConstraintCollectionTest2.cs
mcs/class/System.Data/Test/System.Data/DataSetTest2.cs

index 9d2b3479b013ef3cf6bec00f1fa7e2fc09de4a68,635867cd6d6af5106194c4fbebd475bec1730ff6..5f560e6f76907ec5e83d96d7b0a4aecbbe6c3a20
++2006-03-20  Senganal T  <tsenganal@novell.com>
++
++      * DataSet.cs :
++              - CopyRelations () : When copying the relation, do not add constraints
++              automatically for the relation.
++              - OnMergeFailed () : If merge fails and no handler is set for the MergeFailedEvent,
++              then throw DataException 
++      * ConstraintCollection.cs :
++              - Add () : Check if a constraint already exists on the Columns that are being 
++              constrained.
++              - IndexOf () : Do not check for equivalent constraints, check for the exact instance.
++      * MergeManager.cs (): 
++              -  AdjustSchema () : 
++                      - Handle the MissingSchemaAction.Error case, 
++                      - Do not create constraints when mergin the DataRelation
++                      - Follow the semantics for schema merge/validation  when constraints are already present
++                      in the target DataSet.
++              - AdjustPrimaryKeys () :
++                      - Code cleanup
++                      - Verify Order of Columns in the PrimaryKey when merging.
++              - ResolveColumns : Changed the arument to DataSet. Simplifies code elsewhere.
++              - CompareColumnArrays, CompareColumnArrays : Helper funtions.
++              
+ 2006-03-09  Senganal T  <tsenganal@novell.com>
+       * DataRow.cs :
+               - RejectChanges () :  Add the row to index, if it was in deleted state and
+               Update the index if in Modified State.
+               - AcceptChanges () : Do not update the Indexes.
+               - EndEdit () : Update the indexes even if BeginLoadData has been called
+               on the table. Ideally, indexes should not be maintained during DataLoad,
+               but this needs to handled in multiple places correctly. For now, just maintain
+               the index to ensure correct operation.
+       
+ 2006-03-05  Senganal T  <tsenganal@novell.com>
+       * DataSet.cs :
+               - BeginInit (), EndInit () : Implemented methods
+               - InitInProgress : Added.
+       * DataTable.cs
+               - EndInit () : Move the adding of columns and constraints
+               to FinishInit.
+               - FinishInit () : Added. Adds the Constraints and Columns
+               to the collection.
+               - InitInProgress : Added.
+       * Constraint.cs
+               - FinishInit () : Added. Virtual method
+               - InitInProgress : Added. Virtual property
+       * UniqueConstraint.cs
+       * ForeignKeyConstraint.cs
+               - FinishInit () : Added.
+               - InitInProgress : Added.
+               - DataColsNotValidated : Removed.
+       * ConstraintCollection.cs
+               - PostAddRange : Removed event
+               - PostEndEdit () : Renamed to PostAddRange
+               - Add () : Simplified the testing if constraint is initialized
+               - AddRange () : Simplified initializing the constraints
+       * DataTableCollection.cs
+               - PostAddRange () : Added. Adds the tables to the collection
+       * DataColumnColletion.cs
+               - PostEndInit () : Renamed to PostAddRange.Also, add column to
+               the collection only if not null.
+  
+       Added/Implemented methods for design time support. Renamed some methods for consistency
+       in naming across classes for methods serving the same purpose. 
+ 2006-02-24  Senganal T  <tsenganal@novell.com>
+       * UniqueConstraint.cs :
+               - ChildConstraint : Added. Simplifies verifying if constraints are
+               related.
+               - CanRemoveFromCollection : Fixed the check to verify if constraints is
+               linked to a ForeignKeyConstraint. Fixes #77630
+       * ForeignKeyConstraint.cs :
+               - _validateRemoveParentConstraint : Removed. Not used anymore
+               - ParentConstraint : Added. Simplifies verifying if constraints are
+ 2006-02-22  Senganal T  <tsenganal@novell.com>
+       * DataRow.cs 
+               - RejectChanges : Do not remove Row from Indexes when state is Deleted.
+               - CheckChildRows : When checking for the ChildRows, use the current value
+               and not the original value.
+ 2006-02-18  Atsushi Enomoto  <atsushi@ximian.com>
+       * CustomDataClassGenerator.cs : Patch by Marek Habersack. xsd now
+         outputs AutoIncrement, AutoIncrementSeed, AutoIncrementStep and
+         ReadOnly properties. This fixes bug #77576.
+ 2006-02-17  Chris Toshok  <toshok@ximian.com>
+       * System.Data/DataSet.cs, System.Data/DataView.cs,
+       System.Data/ForeignKeyConstraint.cs,
+       System.Data/DataViewManager.cs, System.Data/DataRow.cs,
+       System.Data/DataSysDescriptionAttribute.cs,
+       System.Data/UniqueConstraint.cs, System.Data/DataTable.cs,
+       System.Data/DataRelation.cs: lots of attribute work, removing
+       DataSysDescription atributes (and marking the class obsolete) for
+       2.0.
+ 2006-02-17  Chris Toshok  <toshok@ximian.com>
+       * DataAdapterException.cs: remove this file.
+       
+ 2006-02-17  Chris Toshok  <toshok@ximian.com>
+       * DataTableReader.cs: Switch to the (bool) form of Dispose to
+       override, as the no-arg form isn't virtual.
+       * Constraint.cs: #ifdef out more DataSysDescriptions.
+       * ConstraintException.cs: add ..ctor (string, Exception) for 2.0.
+ 2006-02-17  Chris Toshok  <toshok@ximian.com>
+       * DataColumn.cs: #ifdef all the DataSysDescriptions !NET_2_0.
+       * AdapterMappingException.cs: nuke this file.
+       * IDbAsyncConnection.cs, IDbAsyncCommand.cs, IGetTypedData.cs,
+       ISetTypedData.cs, IDataReader2.cs, IDataSources.cs,
+       IDbExecutionContext.cs, IDataRecord2.cs, IDataUpdatableRecord.cs:
+       remove these 2.0 files.
+ 2006-02-17  Chris Toshok  <toshok@ximian.com>
+       * ConstraintCollection.cs: in 2.0, class is not serializable and
+       is sealed.  make all the "virtuals" #if !NET_2_0 as well.
+       * Constraint.cs: not serializable in 2.0.
+       * DataColumnCollection.cs: in 2.0, class is not serializable and
+       is sealed.  make all the "virtuals" #if !NET_2_0 as well.
+       * DataRelationCollection.cs: not serializable in 2.0.
+       * DataRelation.cs: not serializable in 2.0.
+       * DataRowBuilder.cs: class is sealed in 2.0.
+       * DataRowCollection.cs: in 2.0, class is not serialized and is
+       sealed.  Also, Add isn't virtual in 2.0 (as the class is sealed).
+       * DataRow.cs: not serializable in 2.0.
+       * DataSet.cs: remove some DataSysDescriptions from the 2.0 build,
+       and s/GetDataReader/CreateDataReader.
+       * DataTableCollection.cs: in 2.0, class is not serializable and is
+       sealed.  make all the "virtuals" #if !NET_2_0 as well.
+       * DataTableReader.cs: remove VisibleFieldCount property.
+       * DataViewSettingCollection.cs: not serializable in 2.0.
+       * DataViewSetting.cs: not serializable in 2.0.
+       * ForeignKeyConstraint.cs: serializable in 2.0.
+       * OperationAbortedException.cs: class is sealed and serializable.
+       * PropertyCollection.cs: serializable in 2.0.
+       * StatementCompletedEventArgs.cs: class is sealed.
+       * UniqueConstraint.cs: not serializable in 2.0.
+ 2006-02-16  Senganal T  <tsenganal@novell.com>
+       * XmlSchemaWriter :
+               WriteDataSetElement : Add an annotation element if exists.
+               WriteDataRelationAnnotation : New. Write a DataRelation as an annotation.
+               WriteConstraints : Write ForeignKeyConstraint even when not associated with
+                       a DataRelation and add a "ConstraintOnly=true" attribute for such constraints.
+       * XmlConstants.cs : Add a new constant - ConstraintOnly
+       * XmlSchemaImporter.cs :
+               - ConstraintStructure : Add field ,IsConstraintOnly, to distinguish if a foreignkeyconstraint
+                       is related to relation or not.
+               - GenerateRelation : Handle the case when parentkey and childkey contain multiple columnnames.
+ 2006-02-11  Senganal T  <tsenganal@novell.com>
+       
+       * UniqueConstraint.cs :
+               - PostAddRange : Check PrimaryKey is not already set for the table
+       * DataTable.cs :
+               - PrimaryKey : follow ms.net behavior when BeginInit , EndInit is used.
+                       - Add new priamry key only when EndInit is called.
+                       - Incase of an error, retain old primarykey 
+               - EndInit :
+                       - Add Constraints after columns are added.
+                       - If both PrimaryKey Property and PrimaryKey Constraint are set,
+                       then the Constraint takes precedence.
+               fixes bug #77404
+ 2006-02-03  Senganal T  <tsenganal@novell.com>
+       * DataTableCollection.cs : 
+               - Remove () : Check for invalid TableName
+               - Add () : Verify the table doesn't belong to another dataset
+       * DataView.cs :
+               - CompleteLastAdded () : Do not raise ItemAdded Event as it is
+                       already raised in AddNew().
+       * DataColumn.cs :
+               - Expression : Verify that the Column names in the expression are valid 
+               - ResetCollectionInfo : Renamed to ResetColumnInfo
+       * DataRow.cs :
+               - RejectChanges () : Reorganized the code to do the Right thing.
+               - Item  : Dont check for detached and deleted rows as these are
+                       done elsewhere.
+       * DataRowCollection.cs :
+               - Add () : Check for null value
+       * DataTable.cs :
+               - PrimaryKey : Set AllowDBNull=false for all the key columns
+               - ImportRow : Import the row only if it is not in Detached state. if in Deleted
+                       state, perform the validation when AcceptChanges/RejectChanges is called.
+       * DataColumnCollection.cs :
+               - Add : Validate the column expression before adding it to the collection.
+               - GetColumnDependency () : New. Get the dependencies on the column 
+               - CanRemove : Move checks to GetColumnDependency
+               - Clear () : Simplified code. Remove unncessary checks.Also, dont check Expression col.
+               - IndexOf - Check argument.
+               Overall , appropriate error msg's are thrown if Remove/Clear fails. Removed a few
+               redundant checks performed and moved the common code to GetColumnDependency.
+ 2006-01-31  Senganal T  <tsenganal@novell.com>
+       * DataSet.cs : Modified CopyRelations ()
+               - Added code to copy ForeignKeyConstraints. Fixes #77411.
+       
+ 2006-01-18 Boris Kirzner <borisk@mainsoft.com>
+       * DataColumn.cs: added PropertyCchangedEvent handling.
+ 2006-01-17  Senganal T  <tsenganal@novell.com>
+       
+       * DataRow.cs:
+               ItemArray : Modified to raise RowInTableException only if
+               the concerned row has been removed from the table.Fixes 
+               bug #77267
+ 2006-01-16 Boris Kirzner <borisk@mainsoft.com>
+       * DataTable.cs: Drop dependend indexes on column removal.
+ 2006-01-16  Atsushi Enomoto  <atsushi@ximian.com>
+       * CustomDataClassGenerator.cs :
+         When a DataRelation connects the same table as parent and child,
+         generate parent row property as BlahRowParent. Fixed bug #77248.
+ 2006-01-10  Senganal T <tsenganal@novell.com>
+       * DataRowCollection.cs
+               - Added ListChangedEvent to notify reset of the collection.
+       * DataView.cs
+               - Subscribes to the ListChangedEvent of DataRowCollection
+               Fixes bug #77188
+ 2006-01-09  Senganal T <tsenganal@novell.com>
+       * RelatedDataView.cs
+       * DataColumn.cs
+               - Resolving a name clash in IExpression
+ 2006-01-06  Senganal T <tsenganal@novell.com>
+       
+       * DataColumn.cs
+       * DataColumnCollection.cs
+               - Reset the Parameters of DataColumn to Default Values when 
+               column is removed from the Table's Collection
+ 2006-01-03  Senganal T <tsenganal@novell.com>
+       * DataTable.cs :
+               - ParseSortString() : Changed the way the sort string is parsed.
+               Using a regex to parse the string.Fixes bug #77104
  2005-12-12  Konstantin Triger <kostat@mainsoft.com>
  
        * DataRow.cs: Added index Updates.
index 8450de856177c6cdbb18d11ced3c60348e8b3393,54746291289233119745851f1b086d2d21d059ce..485f8dd4dab34a1959919938f6f54c5a15e23047
@@@ -159,7 -171,7 +171,15 @@@ namespace System.Data 
                                throw new ArgumentException("Constraint already belongs to this collection.");
                        if (null != constraint.ConstraintCollection) 
                                throw new ArgumentException("Constraint already belongs to another collection.");
-                       
++                      //check if a constraint already exists for the datacolums
++                      foreach (Constraint c in this) {
++                              if (!c.Equals (constraint))
++                                      continue;
++                              throw new DataException ("Constraint matches contraint named '" + c.ConstraintName
++                                                      + "' already in collection"); 
++                      }
++
                        //check for duplicate name
                        if (_isDuplicateConstraintName(constraint.ConstraintName,null)  )
                                throw new DuplicateNameException("Constraint name already exists.");
  
                public int IndexOf(Constraint constraint) 
                {
--                      return List.IndexOf(constraint);
++                      int index = 0;
++                      foreach (Constraint c in this) {
++                              if (c == constraint)
++                                      return index;
++                              index++;
++                      }
++                      return -1;
                }
  
-               public virtual int IndexOf(string constraintName) 
+               public
+ #if !NET_2_0
+               virtual
+ #endif
+               int IndexOf(string constraintName) 
                {
                        //LAMESPEC: Spec doesn't say case insensitive
                        //it should to be consistant with the other 
index 410144198afc466b615a4f6941ff097ae87c7b11,e3d228bf893ccd25390a1bafb347fbdbc3eea695..8a3fa6625d324fec80b37fd22ebff3e0a9c8d360
@@@ -478,21 -506,31 +506,31 @@@ namespace System.Data 
                                        i++;\r
                                }\r
                                \r
--                              DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC);\r
-                               //cRel.ChildColumns = MyRelation.ChildColumns;\r
-                               //cRel.ChildTable = MyRelation.ChildTable;\r
-                               //cRel.ExtendedProperties = cRel.ExtendedProperties; \r
-                               //cRel.Nested = MyRelation.Nested;\r
-                               //cRel.ParentColumns = MyRelation.ParentColumns;\r
-                               //cRel.ParentTable = MyRelation.ParentTable;\r
-                                                               \r
++                              DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC, false);\r
                                Copy.Relations.Add (cRel);\r
                        }\r
+                       \r
+                       // Foreign Key constraints are not cloned in DataTable.Clone\r
+                       // so, these constraints should be cloned when copying the relations.\r
+                       foreach (DataTable table in this.Tables) {\r
+                               foreach (Constraint c in table.Constraints) {\r
+                                       if (!(c is ForeignKeyConstraint) \r
+                                               || Copy.Tables[table.TableName].Constraints.Contains (c.ConstraintName))\r
+                                               continue;\r
+                                       ForeignKeyConstraint fc = (ForeignKeyConstraint)c;\r
+                                       DataTable parentTable = Copy.Tables [fc.RelatedTable.TableName];\r
+                                       DataTable currTable = Copy.Tables [table.TableName];\r
+                                       DataColumn[] parentCols = new DataColumn [fc.RelatedColumns.Length];\r
+                                       DataColumn[] childCols = new DataColumn [fc.Columns.Length];\r
+                                       for (int j=0; j < parentCols.Length; ++j)\r
+                                               parentCols [j] = parentTable.Columns[fc.RelatedColumns[j].ColumnName];\r
+                                       for (int j=0; j < childCols.Length; ++j)\r
+                                               childCols [j] = currTable.Columns[fc.Columns[j].ColumnName];\r
+                                       currTable.Constraints.Add (fc.ConstraintName, parentCols, childCols);\r
+                               }\r
+                       }\r
                }\r
  \r
-               \r
\r
\r
                public DataSet GetChanges ()\r
                {\r
                        return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);\r
                {\r
                        if (MergeFailed != null)\r
                                MergeFailed (this, e);\r
++                      else\r
++                              throw new DataException (e.Conflict);\r
                }\r
  \r
                [MonoTODO]\r
index 5080dbb947923df4e013f5b002577edb586db692,5080dbb947923df4e013f5b002577edb586db692..f7e5b43d27dd67610780f26142fb49093fa8f043
@@@ -40,6 -40,6 +40,7 @@@ namespace System.Dat
  
                        bool prevEC = targetSet.EnforceConstraints;
                        targetSet.EnforceConstraints = false;
++
                        foreach (DataTable t in sourceSet.Tables)
                                MergeManager.Merge(targetSet, t, preserveChanges, missingSchemaAction);
  
                // return false if adjusting fails.
                private static bool AdjustSchema(DataSet targetSet, DataSet sourceSet, MissingSchemaAction missingSchemaAction)
                {
--                      if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey) {
--                              foreach (DataRelation relation in sourceSet.Relations) {
--                                      // TODO : add more precise condition (columns)
--                                      if (!targetSet.Relations.Contains(relation.RelationName)) {
--                                              DataTable targetTable = targetSet.Tables[relation.ParentColumns[0].Table.TableName];
--                                              DataColumn[] parentColumns = ResolveColumns(sourceSet,targetTable,relation.ParentColumns);
--                                              targetTable = targetSet.Tables[relation.ChildColumns[0].Table.TableName];
--                                              DataColumn[] childColumns = ResolveColumns(sourceSet,targetTable,relation.ChildColumns);
--                                              if (parentColumns != null && childColumns != null) {
--                                                      DataRelation newRelation = new DataRelation(relation.RelationName,parentColumns,childColumns);
--                                                      newRelation.Nested = relation.Nested; 
--                                                      targetSet.Relations.Add(newRelation);
--                                              }
++                      if (missingSchemaAction == MissingSchemaAction.Ignore)
++                              return true;
++
++                      foreach(DataTable sourceTable in sourceSet.Tables) {
++
++                              DataTable targetTable = targetSet.Tables[sourceTable.TableName];
++                              if (targetTable == null) 
++                                      continue;
++                              
++                              foreach (Constraint constraint in sourceTable.Constraints) {
++
++                                      Constraint targetConstraint = null;
++
++                                      string constraintName = constraint.ConstraintName;
++                                      if (targetTable.Constraints.Contains (constraintName))
++                                              constraintName = "";
++
++                                      UniqueConstraint uc = constraint as UniqueConstraint;
++                                      // PrimaryKey is already taken care of while merging the table
++                                      // ForeignKey constraint takes care of Parent Unique Constraints
++                                      if (uc != null) {
++                                              if (uc.IsPrimaryKey || uc.ChildConstraint != null)
++                                                      continue;
++                                              DataColumn[] columns = ResolveColumns (targetSet, uc.Columns);
++                                              targetConstraint = new UniqueConstraint (constraintName, columns, false);
                                        }
--                                      else {
--                                              // TODO : should we throw an exeption ?
++
++                                      ForeignKeyConstraint fc = constraint as ForeignKeyConstraint;
++                                      if (fc != null) {
++                                              DataColumn[] columns = ResolveColumns (targetSet, fc.Columns);
++                                              DataColumn[] relatedColumns = ResolveColumns (targetSet, fc.RelatedColumns);
++                                              targetConstraint = new ForeignKeyConstraint (constraintName, relatedColumns, columns);
                                        }
--                              }                       
--
--                              foreach(DataTable sourceTable in sourceSet.Tables) {                            
--                                      DataTable targetTable = targetSet.Tables[sourceTable.TableName];
--
--                                      if (targetTable != null) {
--                                              foreach(Constraint constraint in sourceTable.Constraints) {
--
--                                                      if (constraint is UniqueConstraint) {
--                                                              UniqueConstraint uc = (UniqueConstraint)constraint;
--                                                              // FIXME : add more precise condition (columns)
--                                                              if ( !targetTable.Constraints.Contains(uc.ConstraintName) ) {           
--                                                                      DataColumn[] columns = ResolveColumns(sourceSet,targetTable,uc.Columns);
--                                                                      if (columns != null) {
--                                                                              UniqueConstraint newConstraint = new UniqueConstraint(uc.ConstraintName,columns,uc.IsPrimaryKey);
--                                                                              targetTable.Constraints.Add(newConstraint);
--                                                                      }
--                                                              }
--                                                              else {
--                                                                      // FIXME : should we throw an exception ?
--                                                              }
--                                                      }
--                                                      else {
--                                                              ForeignKeyConstraint fc = (ForeignKeyConstraint)constraint;
--                                                              // FIXME : add more precise condition (columns)
--                                                              if (!targetTable.Constraints.Contains(fc.ConstraintName)) {
--                                                                      DataColumn[] columns = ResolveColumns(sourceSet,targetTable,fc.Columns);
--                                                                      DataTable relatedTable = targetSet.Tables[fc.RelatedTable.TableName];
--                                                                      DataColumn[] relatedColumns = ResolveColumns(sourceSet,relatedTable,fc.RelatedColumns);
--                                                                      if (columns != null && relatedColumns != null) {
--                                                                              ForeignKeyConstraint newConstraint = new ForeignKeyConstraint(fc.ConstraintName,relatedColumns,columns);
--                                                                              targetTable.Constraints.Add(newConstraint);
--                                                                      }
--                                                              }
--                                                              else {
--                                                                      // FIXME : should we throw an exception ?
--                                                              }
--                                                      }
--                                              }
++
++                                      bool dupConstraintFound = false;
++                                      foreach (Constraint cons in targetTable.Constraints) {
++                                              if (!targetConstraint.Equals (cons))
++                                                      continue;
++                                              dupConstraintFound = true;
++                                              break;
                                        }
++
++                                      // If equivalent-constraint already exists, then just do nothing
++                                      if (dupConstraintFound)
++                                              continue;
++
++                                      if (missingSchemaAction == MissingSchemaAction.Error)
++                                              throw new DataException ("Target DataSet missing " + targetConstraint.GetType () +
++                                                              targetConstraint.ConstraintName);
++                                      else
++                                              targetTable.Constraints.Add (targetConstraint);
++                              }
++                      }
++
++                      foreach (DataRelation relation in sourceSet.Relations) {
++                              DataRelation targetRelation = targetSet.Relations [relation.RelationName];
++                              if (targetRelation == null) {
++                                      if (missingSchemaAction == MissingSchemaAction.Error)
++                                              throw new ArgumentException ("Target DataSet mising definition for " +
++                                                               relation.RelationName);
++
++                                      DataColumn[] parentColumns = ResolveColumns (targetSet, relation.ParentColumns);
++                                      DataColumn[] childColumns = ResolveColumns (targetSet, relation.ChildColumns);
++                                      targetRelation = targetSet.Relations.Add (relation.RelationName, parentColumns,
++                                                                              childColumns, false);
++                                      targetRelation.Nested = relation.Nested;
++                              } else if (!CompareColumnArrays (relation.ParentColumns, targetRelation.ParentColumns) ||
++                                              !CompareColumnArrays (relation.ChildColumns, targetRelation.ChildColumns)) {
++                                      RaiseMergeFailedEvent (null, "Relation " + relation.RelationName +
++                                              " cannot be merged, because keys have mismatch columns.");
                                }
                        }
  
                        return true;
                }
  
--              private static DataColumn[] ResolveColumns(DataSet targetSet,DataTable targetTable,DataColumn[] sourceColumns)
++              private static DataColumn[] ResolveColumns(DataSet targetSet, DataColumn[] sourceColumns)
                {
                        if (sourceColumns != null && sourceColumns.Length > 0) {
--                              // TODO : worth to check that all source colums come from the same table
++                              // lets just assume that all columns are from the Same table
++                              DataTable targetTable = targetSet.Tables [sourceColumns[0].Table.TableName];
                                if (targetTable != null) {
                                        int i=0;
                                        DataColumn[] targetColumns = new DataColumn[sourceColumns.Length];
++
++                                      DataColumn tmpCol ;
                                        foreach(DataColumn sourceColumn in sourceColumns) {
--                                              targetColumns[i++] = targetTable.Columns[sourceColumn.ColumnName];
++                                              tmpCol = targetTable.Columns[sourceColumn.ColumnName];
++                                              if (tmpCol == null)
++                                                      throw new DataException ("Column " + sourceColumn.ColumnName  + 
++                                                                      " does not belong to table " + targetTable.TableName);
++                                              targetColumns [i++] = tmpCol;
                                        }
                                        return targetColumns;
                                }
                        return null;
                }
  
--              
++
                // adjust the table schema according to the missingschemaaction param.
                // return false if adjusting fails.
                private static bool AdjustSchema(DataSet targetSet, DataTable sourceTable, MissingSchemaAction missingSchemaAction, ref DataTable newTable)
                {
--                      string tableName = sourceTable.TableName;
--                      
                        // if the source table not exists in the target dataset
                        // we act according to the missingschemaaction param.
--                      int tmp = targetSet.Tables.IndexOf(tableName);
--                      // we need to check if it is equals names
--                      if (tmp != -1 && !targetSet.Tables[tmp].TableName.Equals(tableName))
--                              tmp = -1;
--                      if (tmp == -1) {
--                              if (missingSchemaAction == MissingSchemaAction.Ignore) {
++                      DataTable targetTable = targetSet.Tables [sourceTable.TableName];
++                      if (targetTable == null) {
++                              if (missingSchemaAction == MissingSchemaAction.Ignore)
                                        return true;
--                              }
--                              if (missingSchemaAction == MissingSchemaAction.Error) {
--                                      throw new ArgumentException("Target DataSet missing definition for "+ tableName + ".");
--                              }
--                              
--                              DataTable cloneTable = (DataTable)sourceTable.Clone();
--                              targetSet.Tables.Add(cloneTable);
--                              tableName = cloneTable.TableName;
--                      }                                                               
--                      
--                      DataTable table = targetSet.Tables[tableName];
--                      
++
++                              if (missingSchemaAction == MissingSchemaAction.Error)
++                                      throw new ArgumentException ("Target DataSet missing definition for " +
++                                                      sourceTable.TableName + ".");
++
++                              targetTable = (DataTable)sourceTable.Clone();
++                              targetSet.Tables.Add(targetTable);
++                      }
++
                        for (int i = 0; i < sourceTable.Columns.Count; i++) {
                                DataColumn sourceColumn = sourceTable.Columns[i];
                                // if a column from the source table doesn't exists in the target table
                                // we act according to the missingschemaaction param.
--                              DataColumn targetColumn = table.Columns[sourceColumn.ColumnName];
++                              DataColumn targetColumn = targetTable.Columns [sourceColumn.ColumnName];
                                if(targetColumn == null) {
--                                      if (missingSchemaAction == MissingSchemaAction.Ignore) {
++                                      if (missingSchemaAction == MissingSchemaAction.Ignore)
                                                continue;
--                                      }
--                                      if (missingSchemaAction == MissingSchemaAction.Error) {
--                                              throw new ArgumentException(("Column '" + sourceColumn.ColumnName + "' does not belong to table Items."));
--                                      }
++                                      if (missingSchemaAction == MissingSchemaAction.Error)
++                                              throw new DataException ("Target table " + targetTable.TableName +
++                                                              " missing definition for column " + sourceColumn.ColumnName);
                                        
--                                      targetColumn = new DataColumn(sourceColumn.ColumnName, sourceColumn.DataType, sourceColumn.Expression, sourceColumn.ColumnMapping);
--                                      table.Columns.Add(targetColumn);
--                              }
--
--                              if (sourceColumn.Unique) {
--                                      try {
--                                              targetColumn.Unique = sourceColumn.Unique;
--                                      }
--                                      catch(Exception e){
--//                                            Console.WriteLine("targetColumn : {0}   targetTable : {1} ",targetColumn.ColumnName,table.TableName);
--                                              foreach(DataRow row in table.Rows) {
--//                                                    Console.WriteLine(row[targetColumn]);
--                                              }
--                                              throw e;
--                                      }
++                                      targetColumn = new DataColumn(sourceColumn.ColumnName, sourceColumn.DataType, 
++                                                              sourceColumn.Expression, sourceColumn.ColumnMapping);
++                                      targetTable.Columns.Add(targetColumn);
                                }
  
                                if(sourceColumn.AutoIncrement) {
                                }
                        }
  
--                      if (!AdjustPrimaryKeys(table, sourceTable)) {
++                      if (!AdjustPrimaryKeys(targetTable, sourceTable))
                                return false;
--                      }
  
--                      newTable = table;
++                      newTable = targetTable;
                        return true;
                }
--              
++      
++      
                // find if there is a valid matching between the targetTable PrimaryKey and the
                // sourceTable primatyKey.
                // return true if there is a match, else return false and raise a MergeFailedEvent.
                private static bool AdjustPrimaryKeys(DataTable targetTable, DataTable sourceTable)
                {
--                      // if the length of one of the tables primarykey if 0 - there is nothing to check.
--                      if (sourceTable.PrimaryKey.Length != 0) {
--                              if (targetTable.PrimaryKey.Length == 0) {
--                                      // if target table has no primary key at all - 
--                                      // import primary key from source table
--                                      DataColumn[] targetColumns = new DataColumn[sourceTable.PrimaryKey.Length];
--                                      
--                                      for(int i=0; i < sourceTable.PrimaryKey.Length; i++){
--                                          DataColumn sourceColumn = sourceTable.PrimaryKey[i];
--                                              DataColumn targetColumn = targetTable.Columns[sourceColumn.ColumnName];
--
--                                              if (targetColumn == null) {
--                                                      // is target table has no column corresponding
--                                                      // to source table PK column - merge fails
--                                                      string message = "Column " + sourceColumn.ColumnName + " does not belongs to table " + targetTable.TableName;
--                                                      MergeFailedEventArgs e = new MergeFailedEventArgs(sourceTable, message);
--                                                      targetTable.DataSet.OnMergeFailed(e);
--                                                      return false;
--                                              }
--                                              else {
--                                                      targetColumns[i] = targetColumn;
--                                              }
--                                      }
--                                      targetTable.PrimaryKey = targetColumns;
--                              }
--                              else {
--                                      // if target table already has primary key and
--                                      // if the length of primarykey is not equal - merge fails
--                                      if (targetTable.PrimaryKey.Length != sourceTable.PrimaryKey.Length) {
--                                              string message = "<target>.PrimaryKey and <source>.PrimaryKey have different Length.";
--                                              MergeFailedEventArgs e = new MergeFailedEventArgs(sourceTable, message);
--                                              targetTable.DataSet.OnMergeFailed(e);
--                                              return false;
--                                      }
--                                      else {
--                                              // we have to see that each primary column in the target table
--                                              // has a column with the same name in the sourcetable primarykey columns. 
--                                              bool foundMatch;
--                                              DataColumn[] targetDataColumns = targetTable.PrimaryKey;
--                                              DataColumn[] srcDataColumns = sourceTable.PrimaryKey;
--
--                                              // loop on all primary key columns in the targetTable.
--                                              for (int i = 0; i < targetDataColumns.Length; i++) {
--                                                      foundMatch = false;
--                                                      DataColumn col = targetDataColumns[i];
--
--                                                      // find if there is a column with the same name in the 
--                                                      // sourceTable primary key columns.
--                                                      for (int j = 0; j < srcDataColumns.Length; j++) {
--                                                              if (srcDataColumns[j].ColumnName == col.ColumnName) {
--                                                                      foundMatch = true;
--                                                                      break;
--                                                              }
--                                                      }
--                                                      if (!foundMatch) {
--                                                              string message = "Mismatch columns in the PrimaryKey : <target>." + col.ColumnName + " versus <source>." + srcDataColumns[i].ColumnName + ".";
--                                                              MergeFailedEventArgs e = new MergeFailedEventArgs(sourceTable, message);
--                                                              targetTable.DataSet.OnMergeFailed(e);
--                                                              return false;
--                                                      }
--                                                      
--                                              }
--                                      }
--                              }
++                      if (sourceTable.PrimaryKey.Length == 0)
++                              return true;
++
++                      // If targetTable does not have a PrimaryKey, just import the sourceTable PrimaryKey
++                      if (targetTable.PrimaryKey.Length == 0) {
++                              DataColumn[] targetColumns = ResolveColumns (targetTable.DataSet, sourceTable.PrimaryKey);
++                              targetTable.PrimaryKey = targetColumns;
++                              return true;
++                      }
++                      
++                      // If both the tables have a primary key, verify that they are equivalent.
++                      // raise a MergeFailedEvent if the keys are not equivalent
++                      if (targetTable.PrimaryKey.Length != sourceTable.PrimaryKey.Length) {
++                              RaiseMergeFailedEvent (targetTable, "<target>.PrimaryKey and <source>.PrimaryKey have different Length.");
++                              return false;
                        }
  
++                      for (int i=0; i < targetTable.PrimaryKey.Length; ++i) {
++                              if (targetTable.PrimaryKey [i].ColumnName.Equals (sourceTable.PrimaryKey [i].ColumnName))
++                                      continue;
++                              RaiseMergeFailedEvent (targetTable, "Mismatch columns in the PrimaryKey : <target>." + 
++                                      targetTable.PrimaryKey [i].ColumnName + " versus <source>." + sourceTable.PrimaryKey [i].ColumnName);
++                              return false;
++                      }
                        return true;
                }
--              
++
                // fill the data from the source table to the target table
                private static void fillData(DataTable targetTable, DataTable sourceTable, bool preserveChanges)
                {
                                MergeRow(targetTable, row, preserveChanges);
                        }
                }
--              
++
                // check tha column from 2 tables that has the same name also has the same datatype.
                private static void checkColumnTypes(DataTable targetTable, DataTable sourceTable)
                {
                                DataColumn fromCol = sourceTable.Columns[i];
                                DataColumn toCol = targetTable.Columns[fromCol.ColumnName];
                                if((toCol != null) && (toCol.DataType != fromCol.DataType))
--                                      throw new DataException("<target>." + fromCol.ColumnName + " and <source>." + fromCol.ColumnName + " have conflicting properties: DataType property mismatch.");
++                                      throw new DataException("<target>." + fromCol.ColumnName + " and <source>." + 
++                                                      fromCol.ColumnName + " have conflicting properties: DataType " + 
++                                                      " property mismatch.");
                        }
                }
++
++              private static bool CompareColumnArrays (DataColumn[] arr1, DataColumn[] arr2)
++              {
++                      if (arr1.Length != arr2.Length)
++                              return false;
++
++                      for (int i=0; i < arr1.Length; ++i)
++                              if (!arr1 [i].ColumnName.Equals (arr2 [i].ColumnName))
++                                      return false;
++                      return true;
++              }
++
++              private static void RaiseMergeFailedEvent (DataTable targetTable, string errMsg)
++              {
++                      MergeFailedEventArgs args = new MergeFailedEventArgs (targetTable, errMsg);
++                      targetTable.DataSet.OnMergeFailed (args);
++              }
        }
  }
index b42898b780ac42838459effb6de73d8984e806df,d0e8c600fd44ea6d6196b973202567d503a8d950..d7eb2b870723fdc975ee4837aa85152c6b53d386
++2006-03-20  Senganal T <tsenganal@novell.com>
++
++      * DataSetTest2.cs
++              - Added testcases for issues in Merge,Copy
++      * ConstraintCollectionTest2.cs
++              - Added testcases for issues in Add , IndexOf
++
+ 2006-03-19    Boris Kirzner <borisk@mainsoft.com>
+       
+       * ConstraintCollectionTest2.cs, DataColumnCollectionTest.cs, 
+       DataRowCollectionTest.cs, DataTableCollectionTest.cs: ifdef code that is not 
+       supposed to work in TARGET_JVM by now.
+ 2006-03-09  Senganal T  <tsenganal@novell.com>
+       
+       * DataRowCollectionTest2.cs :
+       * DataTableTest2.cs : 
+               - Fixed NotWorking tests.
+ 2006-03-07  Senganal T  <tsenganal@novell.com>
+       * DataRowCollectionTest2.cs :
+       * DataTableTest2.cs :
+               - Added failing testcases as NotWorking tests.
+ 2006-03-05  Senganal T  <tsenganal@novell.com>
+  
+       * DataSetTest2.cs
+       * ConstraintCollectionTest2.cs
+       * DataViewTest.cs
+       * DataRelationTest.cs
+               Added testcases for BeginInit and EndInit methods
+ 2006-02-24  Senganal T  <tsenganal@novell.com>
+  
+       * ConstraintCollectionTest2.cs : added testcase for #77630
+  
+ 2006-02-22  Senganal T  <tsenganal@novell.com>
+       * DataRowCollectionTest2.cs : Check if index is maintained for row on calling RejectChanges. 
+       * DataTableTest2.cs : Check if data is loaded and merged (if key exists) correctly.
+       * ForeignKeyConstraintTest.cs : Check if a ParentColumn value can be modified
+               when the row is in 'Added' State. Also, check if child col values are
+               updated correctly.
+ 2006-02-16  Senganal T  <tsenganal@novell.com>
+       * DataSetTest2.cs :
+               - WriteXmlSchema_ForeignKeyConstraint : testcase for bug #77557
+               - WriteXmlSchema_RelationAnnotation :
+               - WriteXmlSchema_Relations_ForeignKeys :
+                       ensure Relations and ForeignKeyConstraints are written and read correctly.
+       * DataSetReadXmlSchema.cs :
+               - ReadConstraints :
+                       verify reading a foreignkeyconstraint doesent create a relation.
+               - ReadAnnotatedRelations_MultipleColumns :
+                       verify multiple columns are read correctly if part of annotated relation.
+ 2006-02-11  Senganal T  <tsenganal@novell.com>
+       * DataTableTest.cs : Check AllowDBNull is set to false for PrimaryKey cols.
+       * DataTableTest2.cs : added testcases for bug #77404
+ 2006-02-03  Senganal T  <tsenganal@novell.com>
+       * DataTableCollectionTest2.cs,EvaluateExceptionTest.cs,
+       DataColumnTest.cs,DataRowViewTest.cs,DataRowCollectionTest2.cs,
+       DataTableTest2.cs,DataTableTest.cs,DataColumnCollectionTest2.cs,
+       DataColumnCollectionTest.cs,DataViewTest.cs,DataColumnTest2.cs
+               - Removed 'NotWorking' attributes for the testcases fixed
+               - Added few new testcases
+ 2006-01-17  Senganal T  <tsenganal@novell.com>
+       * DataRowTest2.cs : added testcase for bug #77267
+ 2006-01-16 Boris Kirzner <borisk@mainsoft.com>
+       * DataColumnCollectionTest2.cs: added test case for index update on 
+       column removal
+ 2006-01-16  Atsushi Enomoto  <atsushi@ximian.com>
+       * TypedDataSetGeneratorTest.cs : added test for bug #77248, but we
+         cannot enable it since it depends on mcs "installed".
+ 2006-01-10 Senganal T <tsenganal@novell.com>
+       * DataViewTest2.cs 
+               - Added testcase for bug #77188
+ 2006-01-06 Senganal T <tsenganal@novell.com>
+       * DataColumnTest.cs
+       * DataColumnCollectionTest.cs
+               - Added couple of tests for Expression Columns.
+ 2006-01-03 Senganal T <tsenganal@novell.com>
+       * DataSetTypedDataSetTest.cs : corrected the path to file : TypedDataSet.xml
+       to make sure the testcases pass 
+ 2006-01-03 Senganal T <tsenganal@novell.com>
+       *DataViewTest.cs : added testcases for bug #77104
+ 2006-01-02 Boris Kirzner <borisk@mainsoft.com>
+       * DataTableCollectionTest2.cs, DataColumnTest2.cs,
+       DataViewTest2.cs, DataRowCollectionTest2.cs, DataTableTest2.cs,
+       DataRelationCollectionTest2.cs, ForeignKeyConstraintTest2.cs,
+       DataSetTest2.cs, ConstraintCollectionTest2.cs, DataRowTest2.cs,
+       DataColumnCollectionTest2.cs: new tests from Mainsoft repository.
+       * DataSetTypedDataSetTest.cs, VersionNotFoundException.cs,
+       MissingPrimaryKeyExceptionTest.cs: added files with new tests.
+       * TypedDataSet.xml - new xml file (for TypeDataSetTest.cs).
+ 2005-12-20 Senganal T <tsenganal@novell.com>
+       * DataColumnTest.cs : added testcase for #77025
+       
+ 2005-12-15 Konstantin Triger <kostat@mainsoft.com>
+       * DataTableTest.cs: added SelectRowState test.
+ 2005-12-07 Boris Kirzner <borisk@mainsoft.com>
+       * DataTableTest.cs: added ifdef for feature not supported in TARGET_JVM.
  2005-11-30 Konstantin Triger <kostat@mainsoft.com>
  
        * DataColumnTest.cs: Added ExpressionSubstringlimits.
index 8ba87d693390e8e930881e34e2a1e1665d23b7f8,355434a28ea548b96e12be37af6052f08700dd08..78cba0b2cfec5431c6415d120cef88e0345b2758
@@@ -197,6 -197,6 +197,64 @@@ namespace MonoTests.System.Dat
  
                }
  
++              [Test] public void IndexOf_SameColumns ()
++              {
++                      DataSet ds = new DataSet ();
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++                      DataColumn pcol = table1.Columns.Add ("col1");
++                      DataColumn ccol = table2.Columns.Add ("col1");
++      
++                      ds.Relations.Add ("fk_rel", pcol, ccol); 
++
++                      ForeignKeyConstraint fk = new ForeignKeyConstraint ("fk", pcol, ccol);
++                      Assert.AreEqual (-1, ds.Tables [1].Constraints.IndexOf (fk), "#1");
++              }
++              
++              [Test]
++              public void Add_RelationFirst_ConstraintNext()
++              {
++                      DataSet ds = new DataSet ();
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++                      DataColumn pcol = table1.Columns.Add ("col1");
++                      DataColumn ccol = table2.Columns.Add ("col1");
++      
++                      ds.Relations.Add ("fk_rel", pcol, ccol); 
++
++                      try {
++                              table2.Constraints.Add ("fk_cons", pcol, ccol);
++                              Assert.Fail ("#1 Cannot add duplicate fk constraint");
++                      }catch (DataException e) {
++                      }
++
++                      try {
++                              table1.Constraints.Add ("pk_cons", pcol, false);
++                              Assert.Fail ("#2 Cannot add duplicate unique constraint");
++                      }catch (DataException e) {
++                      }
++              }
++
++              [Test]
++              public void Add_ConstraintFirst_RelationNext ()
++              {
++                      DataSet ds = new DataSet ();
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++                      DataColumn pcol = table1.Columns.Add ("col1");
++                      DataColumn ccol = table2.Columns.Add ("col1");
++      
++                      table2.Constraints.Add ("fk_cons", pcol, ccol);
++
++                      // Should not throw DataException 
++                      ds.Relations.Add ("fk_rel", pcol, ccol);
++
++                      Assert.AreEqual (1, table2.Constraints.Count, "#1 duplicate constraint shudnt be added");
++                      Assert.AreEqual (1, table1.Constraints.Count, "#2 duplicate constraint shudnt be added");
++                      Assert.AreEqual ("fk_cons", table2.Constraints [0].ConstraintName, "#3 shouldnt be overwritten");
++                      Assert.AreEqual ("Constraint1", table1.Constraints [0].ConstraintName, "#4 shouldnt be overwritten");
++              }
++
                [Test] public void IsReadOnly()
                {
                        DataTable dt = DataProvider.CreateUniqueConstraint();
index d11e093cb86bf09546164c7c11e180ab094f9640,962d54959d961640ce2ace28e1ea65a633f09ded..47e33ba547dd6668c205dc7e87e75af1681a4015
@@@ -1362,6 -1418,6 +1418,193 @@@ namespace MonoTests_System.Dat
                        CompareResults_2("merge 3",ds,dsTarget1);
                }
  
++              [Test]
++              public void Merge_RelationWithoutConstraints ()
++              {
++                      DataSet ds = new DataSet ();
++
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++
++                      DataColumn pcol = table1.Columns.Add ("col1", typeof (int));
++                      DataColumn ccol = table2.Columns.Add ("col1", typeof (int));
++
++                      DataSet ds1 = ds.Copy ();
++                      DataRelation rel = ds1.Relations.Add ("rel1", ds1.Tables[0].Columns[0], 
++                                                              ds1.Tables [1].Columns [0], false);
++
++                      ds.Merge (ds1);
++                      Assert.AreEqual (1, ds.Relations.Count , "#1");
++                      Assert.AreEqual (0, ds.Tables [0].Constraints.Count , "#2");
++                      Assert.AreEqual (0, ds.Tables [1].Constraints.Count , "#2");
++              }
++
++              [Test]
++              public void Merge_DuplicateConstraints ()
++              {
++                      DataSet ds = new DataSet ();
++
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++
++                      DataColumn pcol = table1.Columns.Add ("col1", typeof (int));
++                      DataColumn ccol = table2.Columns.Add ("col1", typeof (int));
++
++                      DataSet ds1 = ds.Copy ();
++
++                      DataRelation rel = ds.Relations.Add ("rel1", pcol, ccol);
++
++                      ds1.Tables [1].Constraints.Add ("fk", ds1.Tables [0].Columns [0], ds1.Tables [1].Columns [0]);
++
++                      // No Exceptions shud be thrown
++                      ds.Merge (ds1);
++                      Assert.AreEqual (1, table2.Constraints.Count, "#1 Constraints shudnt be duplicated");
++              }
++
++              [Test]
++              public void Merge_DuplicateConstraints_1 ()
++              {
++                      DataSet ds = new DataSet ();
++
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++
++                      DataColumn pcol = table1.Columns.Add ("col1", typeof (int));
++                      DataColumn ccol = table2.Columns.Add ("col1", typeof (int));
++                      DataColumn pcol1 = table1.Columns.Add ("col2", typeof (int));
++                      DataColumn ccol1 = table2.Columns.Add ("col2", typeof (int));
++
++                      DataSet ds1 = ds.Copy ();
++
++                      table2.Constraints.Add ("fk", pcol, ccol);
++                      ds1.Tables [1].Constraints.Add ("fk", ds1.Tables [0].Columns ["col2"], ds1.Tables [1].Columns ["col2"]);
++
++                      // No Exceptions shud be thrown
++                      ds.Merge (ds1);
++                      Assert.AreEqual (2, table2.Constraints.Count, "#1 fk constraint shud be merged");
++                      Assert.AreEqual ("Constraint1", table2.Constraints [1].ConstraintName, "#2 constraint name shud be changed");
++              }
++
++              [Test]
++              public void CopyClone_RelationWithoutConstraints ()
++              {
++                      DataSet ds = new DataSet ();
++
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++
++                      DataColumn pcol = table1.Columns.Add ("col1", typeof (int));
++                      DataColumn ccol = table2.Columns.Add ("col1", typeof (int));
++
++                      DataRelation rel = ds.Relations.Add ("rel1", pcol, ccol, false);
++
++                      DataSet ds1 = ds.Copy ();
++                      DataSet ds2 = ds.Clone ();
++                      
++                      Assert.AreEqual (1, ds1.Relations.Count, "#1");
++                      Assert.AreEqual (1, ds2.Relations.Count, "#2");
++
++                      Assert.AreEqual (0, ds1.Tables [0].Constraints.Count, "#3");
++                      Assert.AreEqual (0, ds1.Tables [1].Constraints.Count, "#4");
++
++                      Assert.AreEqual (0, ds2.Tables [0].Constraints.Count, "#5");
++                      Assert.AreEqual (0, ds2.Tables [1].Constraints.Count, "#6");
++              }
++
++              [Test]
++              [ExpectedException (typeof (DataException))]
++              public void Merge_MissingEventHandler ()
++              {
++                      DataSet ds = new DataSet ();
++                      DataTable table1 = ds.Tables.Add ("table1");
++
++                      DataColumn pcol = table1.Columns.Add ("col1", typeof (int));
++                      DataColumn pcol1 = table1.Columns.Add ("col2", typeof (int));
++                      
++                      DataSet ds1 = ds.Copy ();
++                      table1.PrimaryKey = new DataColumn[] {pcol};
++                      ds1.Tables [0].PrimaryKey = new DataColumn[] {ds1.Tables [0].Columns [1]};
++
++                      // Exception shud be raised when handler is not set for MergeFailed Event
++                      ds1.Merge (ds);
++              }
++
++              [Test]
++              [ExpectedException (typeof(DataException))]
++              public void Merge_MissingColumn  ()
++              {
++                      DataSet ds = new DataSet ();
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++
++                      table1.Columns.Add ("col1", typeof (int));
++                      table2.Columns.Add ("col1", typeof (int));
++
++                      DataSet ds1 = ds.Copy ();
++
++                      ds1.Tables [0].Columns.Add ("col2");
++
++                      ds.Merge (ds1, true, MissingSchemaAction.Error);
++              }
++
++              [Test]
++              public void Merge_MissingConstraint ()
++              {
++                      DataSet ds = new DataSet ();
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++                      table1.Columns.Add ("col1", typeof (int));
++                      table2.Columns.Add ("col1", typeof (int));
++
++                      try {
++                              DataSet ds1 = ds.Copy ();
++                              DataSet ds2 = ds.Copy ();
++                              ds2.Tables [0].Constraints.Add ("uc", ds2.Tables [0].Columns [0], false);
++                              ds1.Merge (ds2, true, MissingSchemaAction.Error);
++                              Assert.Fail ("#1 If uniqueconstraint is missing, exception shud be thrown");
++                      }catch (DataException e) {
++                      }
++
++                      try {
++                              DataSet ds1 = ds.Copy ();
++                              DataSet ds2 = ds.Copy ();
++                              ds2.Tables [0].Constraints.Add ("fk", ds2.Tables [0].Columns [0], ds2.Tables[1].Columns [0]);
++                              ds1.Tables [0].Constraints.Add ("uc", ds1.Tables [0].Columns [0],false);
++                              ds1.Merge (ds2, true, MissingSchemaAction.Error);
++                              Assert.Fail ("#2 If foreignkeyconstraint is missing, exception shud be thrown");
++                      }catch (DataException e) {
++                      }
++
++                      try {
++                              DataSet ds1 = ds.Copy ();
++                              DataSet ds2 = ds.Copy ();
++                              ds2.Relations.Add ("rel", ds2.Tables [0].Columns [0], ds2.Tables[1].Columns [0], false);
++                              ds1.Merge (ds2, true, MissingSchemaAction.Error);
++                              Assert.Fail ("#2 If datarelation is missing, exception shud be thrown");
++                      }catch (ArgumentException e) {
++                      }
++              }
++
++              [Test]
++              [ExpectedException (typeof (DataException))]
++              public void Merge_PrimaryKeys_IncorrectOrder ()
++              {
++                      DataSet ds = new DataSet ();
++                      DataTable table1 = ds.Tables.Add ("table1");
++                      DataTable table2 = ds.Tables.Add ("table2");
++                      DataColumn pcol = table1.Columns.Add ("col1", typeof (int));
++                      DataColumn pcol1 = table1.Columns.Add ("col2", typeof (int));
++                      DataColumn ccol = table2.Columns.Add ("col1", typeof (int));
++
++                      DataSet ds1 = ds.Copy ();
++                      table1.PrimaryKey = new DataColumn[] {pcol,pcol1};
++                      ds1.Tables [0].PrimaryKey = new DataColumn [] {ds1.Tables[0].Columns [1], ds1.Tables [0].Columns [0]};
++
++                      // Though the key columns are the same, if the order is incorrect
++                      // Exception must be raised
++                      ds1.Merge (ds);
++              }
++
                void CompareResults_1(string Msg,DataSet ds, DataSet dsTarget)
                {
                        // check Parent Primary key length