Browse Source

2006-07-14 Senganal T <[email protected]>

	* Test/System.Data/DataRelationTest2.cs
	* Test/System.Data/ForeignKeyConstraintTest2.cs
	* Test/System.Data/DataColumnTest2.cs
		Tests for DateTimeMode property
	* Test/System.Data/DataTableTest2.cs
		Tests for Merge Methods
	* System.Data/DataTable.cs :
		- Merge - Implement the merge methods
		- Clone - Ensure column's DateTimeMode property is also copied
	* System.Data/DataColumn.cs :
		- DateTimeMode : Implemement
		- DataTypeMatches : Added. In 2.0 profile, test DateTime
		property when verifying column types.
	* System.Data/DataRelation.cs :
		- ctr :  For DateTime columns, check DateTimeMode property
	* System.Data/ForeignKeyConstraint.cs :
		- _validateColumns : For DateTime columns, check DateTimeMode
		property
	* System.Data/MergeManager : 
		- Merge : Added. Overload to merge two tables
		- ResolveColumns : Change the method to use a table instead of
		a DataSet
		- Renamed AdjustSchema to AdjustSchemaRelations


svn path=/trunk/mcs/; revision=62610
Senganal T 19 years ago
parent
commit
282c84fcaa

+ 20 - 0
mcs/class/System.Data/System.Data/ChangeLog

@@ -1,3 +1,23 @@
+2006-07-14  Senganal T  <[email protected]>
+
+	* DataTable.cs :
+		- Merge - Implement the merge methods
+		- Clone - Ensure column's DateTimeMode property is also copied
+	* DataColumn.cs :
+		- DateTimeMode : Implemement
+		- DataTypeMatches : Added. In 2.0 profile, test DateTime
+		property when verifying column types.
+	* DataRelation.cs :
+		- ctr :  For DateTime columns, check DateTimeMode property
+	* ForeignKeyConstraint.cs :
+		- _validateColumns : For DateTime columns, check DateTimeMode
+		property
+	* MergeManager : 
+		- Merge : Added. Overload to merge two tables
+		- ResolveColumns : Change the method to use a table instead of
+		a DataSet
+		- Renamed AdjustSchema to AdjustSchemaRelations
+
 2006-07-13  Senganal T  <[email protected]>
 
 	* DataSet.cs :

+ 61 - 0
mcs/class/System.Data/System.Data/DataColumn.cs

@@ -157,6 +157,39 @@ namespace System.Data {
 			}
 		}
 
+#if NET_2_0
+		DataSetDateTime _datetimeMode = DataSetDateTime.UnspecifiedLocal;
+		[DefaultValue (DataSetDateTime.UnspecifiedLocal)]
+		[RefreshProperties (RefreshProperties.All)]
+		public DataSetDateTime DateTimeMode {
+			get { return _datetimeMode; }
+			set {
+				if (DataType != typeof (DateTime))
+					throw new InvalidOperationException ("The DateTimeMode can be set only on DataColumns of type DateTime.");
+				
+				if (!Enum.IsDefined (typeof (DataSetDateTime), value))
+					throw new InvalidEnumArgumentException ("The DataSetDateTime enumeration value, " + 
+							(int)value + ", is invalid.");
+						
+				if (_datetimeMode == value)
+					return;
+				if (_table == null || _table.Rows.Count == 0) {
+					_datetimeMode = value;
+					return;
+				}
+				if ((_datetimeMode == DataSetDateTime.Unspecified || _datetimeMode == DataSetDateTime.UnspecifiedLocal)
+					&& (value == DataSetDateTime.Unspecified || value == DataSetDateTime.UnspecifiedLocal)) {
+					_datetimeMode = value;
+					return;
+				}
+
+				throw new InvalidOperationException ( String.Format (
+									"Cannot change DateTimeMode from '{0}' to '{1}' " +
+									"once the table has data.",_datetimeMode, value));
+			}
+		}
+#endif
+
 		[DataCategory ("Data")]
 #if !NET_2_0
 		[DataSysDescription ("Indicates whether null values are allowed in this column.")]
@@ -422,6 +455,10 @@ namespace System.Data {
                                         throw new InvalidConstraintException ("Cannot change datatype, " + 
                                                                               "when column is part of a relation");
                                 
+#if NET_2_0
+				if (_dataContainer != null && _dataContainer.Type == typeof (DateTime))
+					_datetimeMode = DataSetDateTime.UnspecifiedLocal;
+#endif
                                 _dataContainer = AbstractDataContainer.CreateInstance(value, this);
 
 				//Check AutoIncrement status, make compatible datatype
@@ -769,6 +806,10 @@ namespace System.Data {
 			//Copy.Site
 			//we do not copy the unique value - it will be copyied when copying the constraints.
 			//Copy.Unique = Column.Unique;
+#if NET_2_0
+			if (DataType == typeof (DateTime))
+				copy.DateTimeMode = _datetimeMode;
+#endif
 			
 			return copy;
 		}
@@ -928,6 +969,26 @@ namespace System.Data {
 			if (_compiledExpression != null)
 				_compiledExpression.ResetExpression ();
 		}
+
+		internal bool DataTypeMatches (DataColumn col)
+		{
+			if (DataType != col.DataType)
+				return false;
+#if NET_2_0
+			if (DataType != typeof (DateTime))
+				return true;
+
+			if (DateTimeMode == col.DateTimeMode)
+				return true;
+			
+			if (DateTimeMode == DataSetDateTime.Local || DateTimeMode == DataSetDateTime.Utc)
+				return false;
+
+			if (col.DateTimeMode == DataSetDateTime.Local || col.DateTimeMode == DataSetDateTime.Utc)
+				return false;
+#endif
+			return true;
+		}
 		#endregion // Methods
 	}
 }

+ 3 - 2
mcs/class/System.Data/System.Data/DataRelation.cs

@@ -113,8 +113,9 @@ namespace System.Data
 					throw new InvalidConstraintException ();
 
 			for (int i=0; i<ChildColumns.Length; i++)
-				if (!( parentColumns[i].DataType.Equals( childColumns[i].DataType)))
-					throw new InvalidConstraintException();
+				if (!parentColumns[i].DataTypeMatches (childColumns[i]))
+					throw new InvalidConstraintException("Parent Columns and Child Columns don't have " + 
+							"matching column types");
 		}
 
 		[MonoTODO]

+ 3 - 3
mcs/class/System.Data/System.Data/DataTable.cs

@@ -1330,19 +1330,19 @@ namespace System.Data {
 		[MonoTODO]
 		public void Merge (DataTable table)
 		{
-			throw new NotImplementedException ();
+			Merge (table, false, MissingSchemaAction.Add);
 		}
 
 		[MonoTODO]
 		public void Merge (DataTable table, bool preserveChanges)
 		{
-			throw new NotImplementedException ();
+			Merge (table, preserveChanges, MissingSchemaAction.Add);
 		}
 
 		[MonoTODO]
 		public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
 		{
-			throw new NotImplementedException ();
+			MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
 		}
 #endif
 

+ 2 - 3
mcs/class/System.Data/System.Data/ForeignKeyConstraint.cs

@@ -257,11 +257,10 @@ namespace System.Data {
 				if (pc == cc)
 					throw new InvalidOperationException("Parent and child columns can't be the same column.");
 
-				if (! pc.DataType.Equals(cc.DataType))
-				{
+				if (!pc.DataTypeMatches (cc)) {
 					//LAMESPEC: spec says throw InvalidConstraintException
 					//		implementation throws InvalidOperationException
-					throw new InvalidConstraintException("Parent column is not type compatible with it's child"
+					throw new InvalidOperationException ("Parent column is not type compatible with it's child"
 						+ " column.");
 				}
 			}

+ 63 - 30
mcs/class/System.Data/System.Data/MergeManager.cs

@@ -44,7 +44,7 @@ namespace System.Data
 			foreach (DataTable t in sourceSet.Tables)
 				MergeManager.Merge(targetSet, t, preserveChanges, missingSchemaAction);
 
-			AdjustSchema(targetSet,sourceSet,missingSchemaAction);
+			AdjustSchemaRelations (targetSet, sourceSet, missingSchemaAction);
 			targetSet.EnforceConstraints = prevEC;
 		}
 
@@ -74,6 +74,28 @@ namespace System.Data
 			}
 		}
 
+		internal static void Merge (DataTable targetTable, 
+					    DataTable sourceTable, 
+					    bool preserveChanges, 
+					    MissingSchemaAction missingSchemaAction)
+		{
+			if(targetTable== null)
+				throw new ArgumentNullException("targetTable");
+			if(sourceTable == null)
+				throw new ArgumentNullException("sourceTable");
+
+			bool savedEnforceConstraints = targetTable.EnforceConstraints;
+			targetTable.EnforceConstraints = false;
+
+			if (!AdjustSchema(targetTable, sourceTable, missingSchemaAction))
+				return;
+
+			checkColumnTypes(targetTable, sourceTable); // check that the colums datatype is the same
+			fillData(targetTable, sourceTable, preserveChanges);
+
+			targetTable.EnforceConstraints = savedEnforceConstraints;
+		}
+
 		internal static void Merge(DataSet targetSet, DataRow[] sourceRows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
 		{
 			if(targetSet == null)
@@ -149,11 +171,7 @@ namespace System.Data
 			}
 		}
 			
-
-		// adjust the dataset schema according to the missingschemaaction param
-		// (relations).
-		// return false if adjusting fails.
-		private static bool AdjustSchema(DataSet targetSet, DataSet sourceSet, MissingSchemaAction missingSchemaAction)
+		private static bool AdjustSchemaRelations (DataSet targetSet, DataSet sourceSet, MissingSchemaAction missingSchemaAction)
 		{
 			if (missingSchemaAction == MissingSchemaAction.Ignore)
 				return true;
@@ -161,9 +179,9 @@ namespace System.Data
 			foreach(DataTable sourceTable in sourceSet.Tables) {
 
 				DataTable targetTable = targetSet.Tables[sourceTable.TableName];
-				if (targetTable == null) 
+				if (targetTable == null)
 					continue;
-				
+
 				foreach (Constraint constraint in sourceTable.Constraints) {
 
 					Constraint targetConstraint = null;
@@ -178,23 +196,24 @@ namespace System.Data
 					if (uc != null) {
 						if (uc.IsPrimaryKey || uc.ChildConstraint != null)
 							continue;
-						DataColumn[] columns = ResolveColumns (targetSet, uc.Columns);
+						DataColumn[] columns = ResolveColumns (targetTable, uc.Columns);
 						targetConstraint = new UniqueConstraint (constraintName, columns, false);
 					}
 
 					ForeignKeyConstraint fc = constraint as ForeignKeyConstraint;
 					if (fc != null) {
-						DataColumn[] columns = ResolveColumns (targetSet, fc.Columns);
-						DataColumn[] relatedColumns = ResolveColumns (targetSet, fc.RelatedColumns);
+						DataColumn[] columns = ResolveColumns (targetTable, fc.Columns);
+						DataColumn[] relatedColumns = ResolveColumns (targetSet.Tables [fc.RelatedTable.TableName],
+											fc.RelatedColumns);
 						targetConstraint = new ForeignKeyConstraint (constraintName, relatedColumns, columns);
 					}
 
 					bool dupConstraintFound = false;
 					foreach (Constraint cons in targetTable.Constraints) {
-						if (!targetConstraint.Equals (cons))
-							continue;
-						dupConstraintFound = true;
-						break;
+					if (!targetConstraint.Equals (cons))
+						continue;
+					dupConstraintFound = true;
+					break;
 					}
 
 					// If equivalent-constraint already exists, then just do nothing
@@ -214,12 +233,14 @@ namespace System.Data
 				if (targetRelation == null) {
 					if (missingSchemaAction == MissingSchemaAction.Error)
 						throw new ArgumentException ("Target DataSet mising definition for " +
-								 relation.RelationName);
+								relation.RelationName);
 
-					DataColumn[] parentColumns = ResolveColumns (targetSet, relation.ParentColumns);
-					DataColumn[] childColumns = ResolveColumns (targetSet, relation.ChildColumns);
+					DataColumn[] parentColumns = ResolveColumns (targetSet.Tables [relation.ParentTable.TableName],
+							relation.ParentColumns);
+					DataColumn[] childColumns = ResolveColumns (targetSet.Tables [relation.ChildTable.TableName],
+							relation.ChildColumns);
 					targetRelation = targetSet.Relations.Add (relation.RelationName, parentColumns,
-										childColumns, false);
+							childColumns, false);
 					targetRelation.Nested = relation.Nested;
 				} else if (!CompareColumnArrays (relation.ParentColumns, targetRelation.ParentColumns) ||
 						!CompareColumnArrays (relation.ChildColumns, targetRelation.ChildColumns)) {
@@ -231,11 +252,10 @@ namespace System.Data
 			return true;
 		}
 
-		private static DataColumn[] ResolveColumns(DataSet targetSet, DataColumn[] sourceColumns)
+		private static DataColumn[] ResolveColumns(DataTable targetTable, DataColumn[] sourceColumns)
 		{
 			if (sourceColumns != null && sourceColumns.Length > 0) {
 				// 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];
@@ -274,14 +294,24 @@ namespace System.Data
 				targetSet.Tables.Add(targetTable);
 			}
 
+			AdjustSchema (targetTable, sourceTable, missingSchemaAction);
+
+			newTable = targetTable;
+			return true;
+		}
+
+
+		private static bool AdjustSchema(DataTable targetTable, DataTable sourceTable, MissingSchemaAction missingSchemaAction)
+		{
+			if (missingSchemaAction == MissingSchemaAction.Ignore)
+				return true;
+
 			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 = targetTable.Columns [sourceColumn.ColumnName];
 				if(targetColumn == null) {
-					if (missingSchemaAction == MissingSchemaAction.Ignore)
-						continue;
 					if (missingSchemaAction == MissingSchemaAction.Error)
 						throw new DataException ("Target table " + targetTable.TableName +
 								" missing definition for column " + sourceColumn.ColumnName);
@@ -301,7 +331,6 @@ namespace System.Data
 			if (!AdjustPrimaryKeys(targetTable, sourceTable))
 				return false;
 
-			newTable = targetTable;
 			return true;
 		}
 	
@@ -316,7 +345,7 @@ namespace System.Data
 
 			// If targetTable does not have a PrimaryKey, just import the sourceTable PrimaryKey
 			if (targetTable.PrimaryKey.Length == 0) {
-				DataColumn[] targetColumns = ResolveColumns (targetTable.DataSet, sourceTable.PrimaryKey);
+				DataColumn[] targetColumns = ResolveColumns (targetTable, sourceTable.PrimaryKey);
 				targetTable.PrimaryKey = targetColumns;
 				return true;
 			}
@@ -355,10 +384,13 @@ namespace System.Data
 			{
 				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.");
+				if (toCol == null)
+					continue;
+				if (toCol.DataTypeMatches (fromCol))
+					continue;
+				throw new DataException("<target>." + fromCol.ColumnName + " and <source>." + 
+						fromCol.ColumnName + " have conflicting properties: DataType " + 
+						" property mismatch.");
 			}
 		}
 
@@ -376,7 +408,8 @@ namespace System.Data
 		private static void RaiseMergeFailedEvent (DataTable targetTable, string errMsg)
 		{
 			MergeFailedEventArgs args = new MergeFailedEventArgs (targetTable, errMsg);
-			targetTable.DataSet.OnMergeFailed (args);
+			if (targetTable.DataSet != null)
+				targetTable.DataSet.OnMergeFailed (args);
 		}
 	}
 }

+ 9 - 0
mcs/class/System.Data/Test/System.Data/ChangeLog

@@ -1,3 +1,12 @@
+2006-07-14  Senganal T <[email protected]>
+
+	* DataRelationTest2.cs
+	* ForeignKeyConstraintTest2.cs
+	* DataColumnTest2.cs
+		Tests for DateTimeMode property
+	* DataTableTest2.cs
+		Tests for Merge Methods
+
 2006-07-13  Senganal T <[email protected]>
 
 	* DataSetTest2.cs : Test for bug #78842

+ 58 - 0
mcs/class/System.Data/Test/System.Data/DataColumnTest2.cs

@@ -28,6 +28,7 @@
 
 using NUnit.Framework;
 using System;
+using System.ComponentModel;
 using System.Data;
 using MonoTests.System.Data.Utils;
 
@@ -796,5 +797,62 @@ namespace MonoTests.System.Data
 			Assert.AreEqual (10, ptable.Rows [0][1], "#1");
 			Assert.AreEqual (-1, ptable.Rows [1][1], "#2");
 		}
+
+#if NET_2_0
+		[Test]
+		public void DateTimeMode_DataType ()
+		{
+			DataColumn col = new DataColumn("col", typeof(int));
+			Assert.AreEqual (DataSetDateTime.UnspecifiedLocal, col.DateTimeMode, "#1");
+			try {
+				col.DateTimeMode = DataSetDateTime.Local;
+				Assert.Fail ("#2");
+			} catch (InvalidOperationException e) {}
+
+			col = new DataColumn ("col", typeof (DateTime));
+			col.DateTimeMode = DataSetDateTime.Utc;
+			Assert.AreEqual (DataSetDateTime.Utc, col.DateTimeMode, "#3");
+			col.DataType = typeof (int);
+			Assert.AreEqual (DataSetDateTime.UnspecifiedLocal, col.DateTimeMode, "#4");
+		}
+	
+		[Test]
+		public void DateTimeMode_InvalidValues ()
+		{
+			DataColumn col = new DataColumn("col", typeof(DateTime));
+			try {
+				col.DateTimeMode = (DataSetDateTime)(-1);
+				Assert.Fail("#1");
+			} catch (InvalidEnumArgumentException e) {}
+
+			try {
+				col.DateTimeMode = (DataSetDateTime)5;
+				Assert.Fail("#2");
+			} catch (InvalidEnumArgumentException e) {}
+		}
+
+		[Test]
+		public void DateTimeMode_RowsAdded ()
+		{
+			DataTable table = new DataTable();
+			table.Columns.Add("col", typeof(DateTime));
+			table.Rows.Add(new object[] {DateTime.Now});
+
+			Assert.AreEqual(DataSetDateTime.UnspecifiedLocal, table.Columns[0].DateTimeMode, "#1");
+			// allowed
+			table.Columns[0].DateTimeMode = DataSetDateTime.Unspecified;
+			table.Columns[0].DateTimeMode = DataSetDateTime.UnspecifiedLocal;
+
+			try {
+				table.Columns[0].DateTimeMode = DataSetDateTime.Local;
+				Assert.Fail("#2");
+			} catch (InvalidOperationException e) {}
+
+			try {
+				table.Columns[0].DateTimeMode = DataSetDateTime.Utc;
+				Assert.Fail("#3");
+			} catch (InvalidOperationException e) {}
+		}
+#endif
 	}
 }

+ 27 - 0
mcs/class/System.Data/Test/System.Data/DataRelationTest2.cs

@@ -532,5 +532,32 @@ namespace MonoTests.System.Data
 			// RelationName get/set
 			Assert.AreEqual("myRelation", dRel.RelationName , "DR63");
 		}
+
+#if NET_2_0
+		[Test]
+		public void DataRelationTest()
+		{
+			DataSet ds = new DataSet();
+			
+			DataTable t1 = new DataTable("t1");
+			t1.Columns.Add("col", typeof(DateTime));
+
+			DataTable t2 = new DataTable("t2");
+			t2.Columns.Add("col", typeof(DateTime));
+			t2.Columns[0].DateTimeMode = DataSetDateTime.Unspecified;
+
+			ds.Tables.Add(t1);
+			ds.Tables.Add(t2);
+			ds.Relations.Add("rel", t1.Columns[0], t2.Columns[0], false);
+
+			ds.Relations.Clear();
+			t2.Columns[0].DateTimeMode = DataSetDateTime.Local;
+
+			try {
+				ds.Relations.Add("rel", t1.Columns[0], t2.Columns[0], false);
+				Assert.Fail ("#1");
+			} catch (InvalidConstraintException) { }
+		}
+#endif
 	}
 }

+ 117 - 0
mcs/class/System.Data/Test/System.Data/DataTableTest2.cs

@@ -2311,6 +2311,123 @@ namespace MonoTests_System.Data
 
 			Assert.AreEqual (6, result [0][0], "# incorrect sorting order");
 		}
+#if NET_2_0
+
+		[Test]
+		public void DataTable_Clone ()
+		{
+			DataTable table = new DataTable ();
+			table.Columns.Add ("col1", typeof (DateTime));
+			table.Columns [0].DateTimeMode = DataSetDateTime.Local;
+			DataTable table1 = table.Clone ();
+			Assert.AreEqual (DataSetDateTime.Local, table1.Columns [0].DateTimeMode, "#1");
+
+			//Test any other new prop in 2.0
+		}
+
+		[Test]
+		public void Merge_SchemaTest ()
+		{
+			DataTable table1 = new DataTable ("t1");
+			table1.Columns.Add ("col1", typeof (int));
+
+			DataTable table2 = new DataTable ("t2");
+			table2.Columns.Add ("col2", typeof (int));
+
+			DataTable table3;
+
+			table3 = table1.Clone ();
+			table3.Merge (table2);
+			Assert.AreEqual (2, table3.Columns.Count, "#1");
+			table3 = table1.Clone ();
+			table3.Merge (table2, false, MissingSchemaAction.Ignore);
+			Assert.AreEqual (1, table3.Columns.Count, "#2");
+
+			// source constraints are ignored
+			table2.Constraints.Add ("uc", table2.Columns [0], false);
+			table3 = table1.Clone ();
+			table3.Merge (table2);
+			Assert.AreEqual (0, table3.Constraints.Count, "#3");
+
+			// source PK is merged depending on MissingSchemaAction
+			table2.PrimaryKey = new DataColumn[] {table2.Columns[0]};
+			table3 = table1.Clone ();
+			table3.Merge (table2);
+			Assert.AreEqual (1, table3.Constraints.Count, "#4");
+			table3 = table1.Clone ();
+			table3.Merge (table2, false, MissingSchemaAction.Ignore);
+			Assert.AreEqual (0, table3.Constraints.Count, "#5");
+
+			//FIXME : If both source and target have PK, then 
+			// shud be the exception raised when schema is merged? 
+			// ms.net throws a nullreference exception.
+			// If any data is merged, exception is anyways raised.
+			/*
+			table1.PrimaryKey = new DataColumn[] {table1.Columns[0]};
+			table3 = table1.Clone ();
+			try {
+				table3.Merge(table2);
+				Assert.Fail("#6");
+			} catch (DataException e) {}
+			*/
+
+			table3.Merge (table2,false,MissingSchemaAction.Ignore);
+			table1.PrimaryKey = null;
+
+			// DateTime columns, DataType match only if DateTimeMode matches
+			table1.Columns.Add ("col_datetime", typeof (DateTime));
+			table2.Columns.Add ("col_datetime", typeof (DateTime));
+			table1.Columns ["col_datetime"].DateTimeMode = DataSetDateTime.Local;
+			table2.Columns ["col_datetime"].DateTimeMode = DataSetDateTime.Unspecified;
+
+			table3 = table1.Clone ();
+			try {
+				table3.Merge (table2);
+				Assert.Fail ("#7");
+			} catch (DataException) { }
+
+			table1.Columns ["col_datetime"].DateTimeMode = DataSetDateTime.Unspecified;
+			table2.Columns ["col_datetime"].DateTimeMode = DataSetDateTime.UnspecifiedLocal;
+			table3 = table1.Clone ();
+			table3.Merge (table2);
+			Assert.AreEqual (DataSetDateTime.Unspecified, table3.Columns ["col_datetime"].DateTimeMode, "#9");
+		}
+
+
+		[Test]
+		public void Merge_TestData ()
+		{
+			DataTable t1 = new DataTable ("t1");
+			DataTable t2 = new DataTable ("t2");
+
+			t1.Columns.Add ("c1", typeof (int));
+			t1.Columns.Add ("c2", typeof (int));
+			t2.Columns.Add ("c1", typeof (int));
+			t2.Columns.Add ("c2", typeof (int));
+
+			t1.Rows.Add (new object[] {1, 1});
+			t1.Rows.Add (new object[] {2, 2});
+
+			t2.Rows.Add (new object[] {1, 5});
+			t2.Rows.Add (new object[] {1, 10});
+
+			DataTable t3 = t1.Copy ();
+			// When primary key is not defined, rows are not merged.
+			t3.Merge (t2);
+			Assert.AreEqual (4, t3.Rows.Count, "#1");
+
+			t1.PrimaryKey = new DataColumn[] {t1.Columns[0]};
+			t3 = t1.Copy ();
+			t3.Merge (t2);
+			Assert.AreEqual (2, t3.Rows.Count, "#2");
+			Assert.AreEqual (10, t3.Rows [0][1], "#3");
+
+			t3 = t1.Copy ();
+			t3.Merge (t2, true);
+			Assert.AreEqual (2, t3.Rows.Count, "#4");
+			Assert.AreEqual (1, t3.Rows [0][1], "#5");
+		}
+#endif
 
 		internal class DataRowsComparer : System.Collections.IComparer
 		{

+ 23 - 0
mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest2.cs

@@ -610,5 +610,28 @@ namespace MonoTests_System.Data
 
 			return ds1;
 		}
+#if NET_2_0
+		[Test]
+		public void ForeignConstraint_DateTimeModeTest()
+		{
+			DataTable t1 = new DataTable("t1");
+			t1.Columns.Add("col", typeof(DateTime));
+
+			DataTable t2 = new DataTable("t2");
+			t2.Columns.Add("col", typeof(DateTime));
+			t2.Columns[0].DateTimeMode = DataSetDateTime.Unspecified;
+			
+			// DataColumn type shud match, and no exception shud be raised 
+			t2.Constraints.Add("fk", t1.Columns[0], t2.Columns[0]);
+
+			t2.Constraints.Clear();
+			t2.Columns[0].DateTimeMode = DataSetDateTime.Local;
+			try {
+				// DataColumn type shud not match, and exception shud be raised 
+				t2.Constraints.Add("fk", t1.Columns[0], t2.Columns[0]);
+				Assert.Fail("#1");
+			} catch (InvalidOperationException e) {}
+		}
+#endif
 	}
 }