10

我正在编写一个简短的算法,它必须比较两个数据集,以便可以进一步处理两者之间的差异。我尝试通过合并这两个 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 中的值不同。两个数据集具有相同的结构。它们由三个数据表组成,这些数据表是数据库中三个查询的结果。合并工作正常,没有问题。

我的问题是:是否有任何合理的解释为什么 foundChanges 变量总是错误的,如果没有,Linq 是否会为这个问题提供适当的解决方案,或者我是否必须通过遍历数据集来确定更改

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

提前致谢

4

3 回答 3

5

我认为问题在于您不了解 .NET 数据集。DataTable 保留加载到其中的每个值的“原始”副本。当一个值发生变化时,DataTable 能够检测到变化。同样,DataTable 跟踪已添加或删除的行。该HasChanges()函数只是爬取数据表并检查是否有任何更改(更改的值、新行、删除的行等)

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

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

看:

下面的代码将通过基于键列查找添加/删除的行来比较两个数据表,并通过比较匹配行的值(同样基于键)来查找修改的行。扩展它来比较数据集(通过比较数据集之间名称相似的表)将是相当简单的。

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。在表 2
中添加记录 3。
在表 2 中修改记录 1。

于 2012-12-27T14:09:03.383 回答
0

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

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

如果两个数据集的架构不同,那么您必须手动执行此操作。

于 2012-12-27T14:17:54.000 回答
-1

正如您从其他一些答案中看到的那样,要区分两个数据集并不容易。

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

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

于 2012-12-27T14:50:41.367 回答