いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

ADO.NET入門記-013 (DataRow.RowStateの遷移について (DataTable, DataRow, DataRowState))


データテーブルを使用する上で、行の状態の遷移はとても大事な概念となります。
DataAdapterのUpdateメソッドは、上記の状態を元にその行のデータをInsertするのかUpdateするのか
Deleteするのかを決定します。


以下、DataRowStateについての簡単なサンプルです。
殴り書きしたので、見栄えが悪いですがご勘弁を。

using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

using NUnit.Framework;

namespace Gsf.Samples.AdoNet {

    [TestFixture()]
    public class AdoNetSample014 {

        [Test()]
        public void DataRowStateの遷移の確認(){
            //
            // テスト用のデータテーブルを作成
            //
            DataTable t = new DataTable();
            t.Columns.Add(new DataColumn("id", typeof(string)));

            //
            // 新規で行を生成.データテーブルとは紐付いていない.
            //
            DataRow r = t.NewRow();

            Assert.AreEqual(DataRowState.Detached, r.RowState);    // Detached.

            //
            // データテーブルに行を追加.
            //
            t.Rows.Add(r);

            Assert.AreEqual(DataRowState.Added, r.RowState);       // Added.

            //
            // 変更を確定.
            //
            t.AcceptChanges();                                     // Unchanged.

            //
            // 行データを更新.
            //
            r["id"] = "hoge";

            Assert.AreEqual(DataRowState.Modified, r.RowState);    // Modified.

            t.AcceptChanges();                                     // Unchanged.

            //
            // 行データを削除対象とする。
            //
            r.Delete();

            Assert.AreEqual(DataRowState.Deleted, r.RowState);     // Deleted.

            //
            // 変更を取り消す.
            //
            t.RejectChanges();

            Assert.AreEqual(DataRowState.Unchanged, r.RowState);   // Unchanged.

            //
            // 強制的に行状態を追加とする。
            //
            r.SetAdded();

            Assert.AreEqual(DataRowState.Added, r.RowState);       // Added.

            t.AcceptChanges();

            //
            // 強制的に行状態を更新とする。
            //
            //
            // ここで、上のAcceptChangesを呼ばないでSetModifiedを呼ぶと
            // エラーとなる。何故なら、RowStateがUnchangedではないから。
            //
            r.SetModified();

            Assert.AreEqual(DataRowState.Modified, r.RowState);    // Modified.


            /////////////////////////////////////////////////////////////////
            //
            // 新たにもう一つ同じデータを持つデータテーブルを用意する。
            //
            // 元のデータテーブルから更新のマークがされている行のみを抽出.
            DataTable t2 = t.GetChanges(DataRowState.Modified);

            DataRow r2 = t2.Rows[0];

            Assert.AreEqual(DataRowState.Modified, r2.RowState);   // Modified.

            t2.AcceptChanges();                                    // Unchanged.

            //
            // 同じ行データなのに、状態が違う。
            // なぜなら、GetChangesで返るのはコピーされたテーブルになるので別物になる。
            //
            Assert.AreEqual(DataRowState.Unchanged, r2.RowState);  // Unchanged.
            Assert.AreEqual(DataRowState.Modified,  r.RowState);   // Modified.

            r2.SetAdded();

            Assert.AreEqual(DataRowState.Added,     r2.RowState);  // Added.
            Assert.AreEqual(DataRowState.Modified,  r.RowState);   // Modified.
        }
    }
}


DataTable.GetChangesメソッドを使用して取得できるデータテーブルオブジェクトは
元のデータテーブルのデータをコピーした全く別物のオブジェクトとなります。


なので、コピーされたデータテーブルの行に対して値を変更しても
元のデータテーブルの該当行のRowStateの値は変わりません。
結構、これハマりますのでご注意を。



================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。