我正在编写一个简短的算法,它必须比较两个数据集,以便可以进一步处理两者之间的差异。 我尝试通过合并这两个数据集并将结果更改放入新的数据集来实现此目标。
我的方法如下所示:
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。
提前致谢
最佳答案
我认为问题是你不理解.NET DataSets。 DataTable 保留加载到其中的每个值的“原始”副本。当值更改时,DataTable 能够检测到更改。同样,DataTable 会跟踪已添加或删除的行。 HasChanges()
函数只是抓取 DataTable 并检查是否有任何更改(更改的值、新行、删除的行等)
请参阅 MSDN 文档:
http://msdn.microsoft.com/en-us/library/system.data.dataset.haschanges.aspx
比较两个数据集很棘手,我不知道有任何内置函数可以处理这个问题(因为每个程序员都有自己的“等效”定义)。
参见:
- How to compare 2 dataTables在 StackOverflow 上
- Comparing DataSets using LINQ在代码项目上
下面的代码将通过基于键列查找添加/删除的行来比较两个数据表,并通过比较匹配行的值(同样基于键)查找修改的行。扩展它来比较数据集(通过比较数据集之间名称相似的表)将是相当简单的。
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 );
}
}
}
控制台输出:
Record 2 was deleted from table 2.
Record 3 was added to table 2.
Record 1 was modified in table 2.
关于c# - 获取 2 个数据集 c# 中的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14055909/