获取2个DataSet的差异c#

我正在编写一个简短的算法,它必须比较两个DataSet,以便可以进一步处理两者之间的差异。 我尝试通过合并这两个DataSet来完成这个目标,并将结果更改到新的DataSet中。

我的方法如下所示:

private DataSet ComputateDiff(DataSet newVersion, DataSet oldVersion) { DataSet diff = null; oldVersion.Merge(newVersion); bool foundChanges = oldVersion.HasChanges(); if (foundChanges) { diff = oldVersion.GetChanges(); } return diff; } 

foundChanges的结果始终为false,即使两个DataSet中的值不同。 两个DataSet都具有相同的结构。 它们由三个DataTable组成,这三个DataTable是数据库中三个查询的结果。 合并工作没有问题。

我的问题是:有没有合理的解释为什么foundChanges变量总是假的,如果不是,Linq会为这个问题提供一个合适的解决方案,或者我必须通过迭代DataSet来确定更改

以下是一些进一步的信息:编程语言是C#我正在使用.Net framework 4.0我在Windows 8机器上开发所提到的数据来自数据库(MSSQL Server 2012 express)我的DataSet或DataTables没有任何PK的我所知道的。

提前致谢

我认为问题是你不了解.NET DataSet。 DataTable保留加载到其中的每个值的“原始”副本。 更改值时,DataTable可以检测到更改。 同样,DataTable会跟踪已添加或删除的行。 HasChanges()函数只是遍历DataTables并检查是否有任何更改(更改的值,新行,已删除的行等)

请参阅MSDN文档:
http://msdn.microsoft.com/en-us/library/system.data.dataset.haschanges.aspx

比较两个DataSet很棘手,我不知道有任何内置函数来处理这个问题(因为每个程序员都有自己的“等价”定义)。

看到:

  • 如何在StackOverflow上比较2个dataTables
  • 使用 CodeProject上的LINQ比较DataSet

下面的代码将通过比较匹配行的值(同样,基于密钥),通过查找基于Key列和已修改行的添加/删除行来比较两个DataTable。 扩展它以比较DataSet(通过比较DataSet之间类似命名的表)将是相当简单的。

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; namespace DataSetComparison { class Program { static void Main( string[] args ) { var l_table1 = new DataTable(); l_table1.Columns.Add( "Key", typeof( int ) ); l_table1.Columns.Add( "Name", typeof( string ) ); l_table1.Columns.Add( "Age", typeof( int ) ); var l_table2 = new DataTable(); l_table2.Columns.Add( "Key", typeof( int ) ); l_table2.Columns.Add( "Name", typeof( string ) ); l_table2.Columns.Add( "Age", typeof( int ) ); l_table1.Rows.Add( l_table1.NewRow() ); l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 0; l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Alfred Harisson"; l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 36; l_table1.Rows.Add( l_table1.NewRow() ); l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 1; l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Matthew George"; l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 41; l_table1.Rows.Add( l_table1.NewRow() ); l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 2; l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Franklin Henry"; l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 33; l_table2.Rows.Add( l_table2.NewRow() ); l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 0; l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Alfred Harisson"; l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 36; l_table2.Rows.Add( l_table2.NewRow() ); l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 1; l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Matthew George"; l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 42; // Record 1 "modified" // Record 2 "deleted" // Record 3 "added": l_table2.Rows.Add( l_table2.NewRow() ); l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 3; l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Lester Kulick"; l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 33; // Using table 1 as the control, find changes in table 2 // Find deleted rows: var l_table2Keys = l_table2.Select().Select( ( r ) => (int) r["Key"] ); var l_deletedRows = l_table1.Select().Where( ( r ) => !l_table2Keys.Contains( (int) r["Key"] ) ); foreach ( var l_deletedRow in l_deletedRows ) Console.WriteLine( "Record " + l_deletedRow["Key"].ToString() + " was deleted from table 2." ); // Find added rows: var l_table1Keys = l_table1.Select().Select( ( r ) => (int) r["Key"] ); var l_addedRows = l_table2.Select().Where( ( r ) => !l_table1Keys.Contains( (int) r["Key"] ) ); foreach ( var l_addedRow in l_addedRows ) Console.WriteLine( "Record " + l_addedRow["Key"].ToString() + " was added to table 2." ); // Find modified rows: var l_modifiedRows = l_table2.Select() .Join( l_table1.Select(), r => (int) r["Key"], r => (int) r["Key"], ( r1, r2 ) => new { Row1 = r1, Row2 = r2 } ) .Where( values => !( values.Row1["Name"].Equals( values.Row2["Name"] ) && values.Row1["Age"].Equals( values.Row2["Age"] ) ) ) .Select( values => values.Row2 ); foreach ( var l_modifiedRow in l_modifiedRows ) Console.WriteLine( "Record " + l_modifiedRow["Key"].ToString() + " was modified in table 2." ); Console.WriteLine( "Press any key to quit..." ); Console.ReadKey( true ); } } } 

控制台输出:

记录2从表2中删除。
记录3被添加到表2中。
记录1在表2中进行了修改。

如果两个数据集的架构相同,那么您可以尝试下面的一个

 Dataset dsTest1 DataSet dsTest2 DataSet dsFinal; dsFinal.Merge(dsTest1); dsFinal.AcceptChanges(); dsFinal.Merge(dsTest2); DifferenceDataSet = dsFinal.GetChanges() 

如果两个数据集的架构不同,则必须手动执行。

从其他一些答案中可以看出,获取两个DataSet的区别并不容易。

这就是DataSet.GetChanges()的目的。 如果您从数据集开始并直接对该数据集进行更改(即,当用户更新单元格时,当用户提交表单等等时),则DataSet会跟踪更改。 这样,您可以调用DataSet.GetChanges()来获取更改(或差异)。 然后,您只能处理更改。

获取初始数据集和最终数据集并获得差异是一个难题。 将最终数据集与旧数据集合并也没有意义,因为最终数据集是合并的结果。