10

2 つの DataSet を比較して、両者の違いをさらに処理できるようにする短いアルゴリズムを作成しています。これら 2 つの 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;
    }

2 つの DataSet の値が異なっていても、foundChanges の結果は常に false です。両方の DataSet の構造は同じです。これらは、データベース内の 3 つのクエリの結果である 3 つの DataTable で構成されます。マージは問題なく動作します。

私の質問は次のとおりです: foundChanges 変数が常に false である合理的な説明はありますか?そうでない場合、Linq はこの問題に対して適切な解決策を提供しますか、それとも DataSets を反復処理して変更を決定する必要がありますか?

プログラミング言語は C# です .Net Framework 4.0 を使用しています Windows 8 マシンで開発しています 前述のデータはデータベース (MSSQL Server 2012 Express) から取得されます 私の DataSets または DataTables には PK がありません私の知る限りでは。

前もって感謝します

4

3 に答える 3

5

問題は、.NETデータセットを理解していないことだと思います。DataTableは、ロードされた各値の「元の」コピーを保持します。値が変更されると、DataTableはその変更を検出できます。同様に、DataTableは追加または削除された行を追跡します。このHasChanges()関数は、DataTableをクロールし、変更(値の変更、新しい行、削除された行など)があったかどうかを確認するだけです。

MSDNのドキュメントを参照してください:http:
//msdn.microsoft.com/en-us/library/system.data.dataset.haschanges.aspx

2つのデータセットを比較するのは難しいです。これを処理するための組み込み関数を私は知りません(すべてのプログラマーが「同等性」の独自の定義を持っているため)。

見る:

以下のコードは、キー列に基づいて追加/削除された行を検索することで2つのDataTableを比較し、一致する行の値を比較することで変更された行を比較します(ここでもキーに基づいています)。これを拡張してデータセットを比較することはかなり簡単です(データセット間で同じ名前のテーブルを比較することによって)。

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で変更されました。

于 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

他のいくつかの回答からわかるように、2 つの DataSet の違いを取得するのは簡単ではありません。

それが DataSet.GetChanges() の目的です。データセットから始めて、そのデータセットに直接変更を加えた場合 (つまり、ユーザーがセルを更新したとき、ユーザーがフォームを送信したときなど)、DataSet は変更を追跡します。このようにして、DataSet.GetChanges() を呼び出して変更 (または差分) を取得できます。その後、変更のみを処理できます。

最初のデータセットと最終的なデータセットを取り、その違いを取得するのは難しい問題です。また、最終的なデータセットはマージの結果であるため、最終的なデータセットを古いデータセットとマージしても意味がありません。

于 2012-12-27T14:50:41.367 に答える