更新中のDataSetに最新情報を取得&をマージする方法

  非接続型データのDataSetは、データソースから取得以降、元データとの同期を常に意識することが重要です。そこで、現在更新中のデータを活かし、元のデータソースから取得した最新のDataSetとマージする方法を示します。
【マージの考え方】
 
 ・ベースとなるDataSetは、最新のDataSetとする。
 ・更新中のデータと比較した差異は以下のように処理する。
   ・更新データは、更新中の値を設定する。
   ・最新データに存在しないレコードの内、更新または追加されたレコードは、新規追加レコードとして挿入する。
【サンプル C#】
///
///  更新中のDataSetに最新のDataSetをマージする
///
///  param name="dsBase":元となるDataSet
///  param name="dsNew":更新するDataSet
///  param name="IndexName":キーとなる列名の文字列配列(配列の順番はTabel順)
public static void DataSetUpdate(  DataSet dsBase, DataSet dsNew, string[] IndexName )
{
    //Debug.WriteLine("DataSetUpdate:開始");

    // 元のDataSetから更新情報を抽出
    DataSet dsUpd = dsBase.GetChanges();
    // 削除用として元のDataSetの複製を生成
    DataSet dsDel = dsBase.Clone();
    // 削除分DataSetの追加扱い処理時のリレーション制約解除
    dsDel.EnforceConstraints = false;

    // 元のDataSetの非更新情報の内、最新DataSetに無いレコードを抽出&元DataSetから削除
    for ( int nTbl=0 ; nTbl < dsBase.Tables.Count ; nTbl++ )
    {
        DataTable tbl   = dsBase.Tables[nTbl];
        int       index = tbl.Columns.IndexOf(IndexName[nTbl]);

        foreach ( DataRow drBase in tbl.Select( "", "", DataViewRowState.Unchanged ))
        {
            DataRow drNew = dsNew.Tables[nTbl].Rows.Find(drBase[index]);

            if ( drNew == null )
            {
                // 削除分の保存と元データから削除
                dsDel.Tables[nTbl].ImportRow(drBase);
                tbl.Rows.Remove(drBase);
            }
        }
        // 追加分を元データから削除
        foreach ( DataRow drBase in tbl.Select( "", "", DataViewRowState.Added ))
        {
            tbl.Rows.Remove(drBase);
        }
    }

    // 再読込みデータを旧データに反映
    dsBase.Merge(dsNew);

    // 更新ステータスをクリア
    dsBase.AcceptChanges();

    // 追加分を含む更新情報を旧データに反映
    if ( dsUpd != null )
    {
        //Debug.WriteLine("DataSetUpdate dsUpd : " + dsUpd.Tables.Count.ToString());

        for ( int nTbl=0 ; nTbl < dsBase.Tables.Count ; nTbl++ )
        {
            DataTable tbl   = dsBase.Tables[nTbl];
            int       index = tbl.Columns.IndexOf(IndexName[nTbl]);

            //Debug.WriteLine("DataSetUpdate dsUpd.Tables[" + tbl.TableName + "] : " + tbl.Rows.Count.ToString());

            // 更新レコードを反映
            foreach ( DataRow dr in dsUpd.Tables[nTbl].Select( "", "", DataViewRowState.ModifiedCurrent ))
            {
                DataRow drBase = tbl.Rows.Find(dr[index]);

                if ( drBase == null )
                {
                    tbl.ImportRow(dr);
                }
                else
                {
                    // 既存レコードに値を代入
                    foreach ( DataColumn col in tbl.Columns )
                    {
                        //自動インクリメント列は除く
                        if ( col.AutoIncrement )
                            continue;

                        // 既存レコードに値を代入
                        drBase[col.Ordinal] = dr[col.Ordinal];
                    }
                }
            }
            // 新規追加レコードを反映
            foreach ( DataRow dr in dsUpd.Tables[nTbl].Select("", "", DataViewRowState.Added))
            {
                DataRow drBase = tbl.Rows.Find(dr[index]);

                if ( drBase == null )
                {
                    tbl.ImportRow(dr);
                }
                else
                {
                    // 既存レコードに値を代入
                    foreach ( DataColumn col in tbl.Columns )
                    {
                        //自動インクリメント列は除く
                        if ( col.AutoIncrement )
                            continue;

                        // 既存レコードに値を代入
                        drBase[col.Ordinal] = dr[col.Ordinal];
                    }
                }
            }
        }
        // 抽出データの開放
        dsUpd.Dispose();
    }

    // 最新版DataSetに存在しないレコードを追加扱いとする
    if ( dsDel != null )
    {
        for ( int nTbl=0 ; nTbl < dsBase.Tables.Count ; nTbl++ )
        {
            DataTable tbl   = dsBase.Tables[nTbl];
            int       index = tbl.Columns.IndexOf(IndexName[nTbl]);

            // 最新版DataSetに存在しないレコードを追加
            foreach ( DataRow dr in dsDel.Tables[nTbl].Rows )
            {
                DataRow drBase = tbl.Rows.Find(dr[index]);

                if ( drBase == null )
                {
                    drBase = tbl.NewRow();

                    // 新規レコードに値を代入(自動インクリメント列は除く)
                    foreach ( DataColumn col in tbl.Columns )
                    {
                        //自動インクリメント列は除く
                        if ( col.AutoIncrement )
                            continue;

                        // 新規レコードに値を代入
                        drBase[col.Ordinal] = dr[col.Ordinal];
                    }
                    tbl.Rows.Add(drBase);
                }
            }
        }
        // 抽出データの開放
        dsDel.Dispose();
    }
    
    //Debug.WriteLine("DataSetUpdate:終了");
}
【注意】
戻る