//****************************************************************************************************** // DataSetEqualityComparer.cs - Gbtc // // Copyright © 2013, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 08/09/2013 - Stephen C. Wills // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.Data; using System.Diagnostics.CodeAnalysis; namespace GSF.Data { /// /// Equality comparer for objects. /// public class DataSetEqualityComparer : IEqualityComparer { private DataSetEqualityComparer() { } /// /// Determines whether the specified objects are equal. /// /// /// true if the specified objects are equal; otherwise, false. /// /// The first object of type to compare. /// The second object of type to compare. public bool Equals(DataSet x, DataSet y) { // If the two data sets are the same object, they are equal if (ReferenceEquals(x, y)) return true; // Test for null if (x is null || y is null) return false; // Check that the number of tables match if (x.Tables.Count != y.Tables.Count) return false; foreach (DataTable xTable in x.Tables) { // Check that both data sets have this table defined if (!y.Tables.Contains(xTable.TableName)) return false; DataTable yTable = y.Tables[xTable.TableName]; // Check that both tables have the same number of rows if (xTable.Rows.Count != yTable.Rows.Count) return false; // Check that both tables have the same number of columns if (xTable.Columns.Count != yTable.Columns.Count) return false; for (int i = 0; i < xTable.Rows.Count; i++) { foreach (DataColumn column in xTable.Columns) { // Check that both tables contain this particular column if (!yTable.Columns.Contains(column.ColumnName)) return false; object xField = xTable.Rows[i][column.ColumnName]; object yField = yTable.Rows[i][column.ColumnName]; if (xField == DBNull.Value || yField == DBNull.Value) { // At least one value is DBNull, // so this checks if they are both DBNull if (xField != yField) return false; } else if (!xField.Equals(yField)) { // The values are not equal return false; } } } } return true; } /// /// Returns a hash code for the specified object. /// /// /// A hash code for the specified object. /// /// The for which a hash code is to be returned. /// The type of is a reference type and is null. public int GetHashCode(DataSet obj) { int hashCode = 0; if (obj is null) throw new ArgumentNullException(nameof(obj)); // This method is required by IEqualityComparer - although the following // should work, this is not likely the most efficient way to do this... foreach (DataTable table in obj.Tables) { foreach (DataRow row in table.Rows) { foreach (DataColumn column in table.Columns) { object field = row[column]; if (field is null) continue; hashCode ^= field.GetHashCode(); } } } return hashCode; } /// /// Default instance of the class. /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly DataSetEqualityComparer Default = new DataSetEqualityComparer(); } }