AcceptChanges()和RejectChanges()原理


今天我遇到一個題目,是關於AcceptChanges()和RejectChanges()方法的,考慮到可能很多人不清楚這些概念。
所以拿出來講講。由這個問題我們也深入了解一下這兩個方法。
為了不在顯示略文時顯示出代碼來,我就在剛開始多打一點字了。呵。。。

題目的代碼如下:

protected void Button1_Click(object sender, EventArgs e)
    {
        DataSet ds= new DataSet();
 
             DataTable tb = ds.Tables.Add("Items");
             DataColumn pk = tb.Columns.Add("ID", typeof(Int32));
             tb.Columns.Add("Items", typeof(string));
             tb.PrimaryKey = new DataColumn[] {pk};
 
            for(int i=0;i<6;i++)
            {
                DataRow dr = tb.NewRow();
                dr[0] = i.ToString();
                dr[1] = "Itme "+i;
                tb.Rows.Add(dr);
            }

            tb.Rows[0].Delete();
            tb.Rows.RemoveAt(1);
            tb.Rows.RemoveAt(2);
            tb.RejectChanges();

 

            GridView1.DataSource = tb;
            GridView1.DataBind();

    }

我們看到在第3-16行,實際上我們是生成了一個DataTable,這個dt有兩個字段,分別是ID和Items,然后通過添加6條記錄。
如果到此為止,那么這個的內容應該是如下:

ID Items
0 Item 0
1 Item 1
2 Item 2
3 Item 3
4 Item 4
5 Item 5

不過我們在第19,20,21行中分別刪除了第0行,然后是移除第1行,移除第2行。當然如果只是這樣就算不上題目了,我們在18和22行用到了DataTable的AcceptChanges()方法和RejectChanages()方法。

首先大家先想一下答案是什么?隨便我把MSDN上對這兩個方法的解釋粘一下,好讓大家理解。

DataTable.AcceptChanges方法
提交自上次調用 AcceptChanges 以來對該表進行的所有更改。調用 AcceptChanges 時,任何仍處於編輯模式的 DataRow 對象將成功結束其編輯。DataRowState 也會隨之更改:所有狀態為 Added 和 Modified 的行的狀態都變為 Unchanged;狀態為 Deleted 的行則被移除。
在您嘗試使用 DbDataAdapter.Update 方法更新 DataSet 之后,通常會對 DataTable 調用 AcceptChanges 方法。

DataTable.RejectChanges方法
回滾自該表加載以來或上次調用 AcceptChanges 以來對該表進行的所有更改。
調用 RejectChanges 時,任何仍處於編輯模式的 DataRow 對象將取消其編輯。新行被移除。DataRowState 設置為 Modified 或 Deleted 的行返回到其初始狀態。

一個意思表示立即更新,一個表示在接受上次調用AcceptChanges后進行回滾。

好的,那么是不是說,我們這兒的3條記錄都能夠回滾回來呢?

我們先公布一下答案吧,看看和大家想的是不是一樣的。

ID Items
0 Item 0
2 Item 2
4 Item 4
5 Item 5


OK,答案表明並不是所有的記錄都被回滾回來了,似乎只有0被回滾了。這並不是奇怪,那是因為我們使用刪除行的方法不一樣,一個是Delete(),一個是RemoveAt(int)。

我們通過在MSDN中的查詢了解到在使用 Delete 方法后,RowState 變成“已刪除”。在您調用 AcceptChanges 之前,它一直保持“已刪除”。可通過調用 RejectChanges 取消刪除行。

而RemoveAt表示當移除行時,該行中的所有數據都將丟失。您還可以調用 DataRow 類的 Delete 方法來標記某行以供移除。調用 RemoveAt 等同於先調用 Delete 再調用 AcceptChanges。

那就是說,我們使用Delete()方法刪除行后是可以回滾的,而使用RemoveAt(int)方法是不能回滾的。
所以剛剛前面我們刪除的三行,只回滾了0的那行是完成正確的。我想大家對答案應該沒有疑問了。

從這個題目中,我引申出幾個題目來,看看大家會不會做哦?

下面接着,我們再來修改一下代碼看看。

tb.Rows[ 0 ].Delete();
tb.AcceptChanges();
tb.Rows.RemoveAt(
1 );
tb.Rows.RemoveAt(
2 );
tb.RejectChanges();


我們把AcceptChanges()方法放到后Delete()后面,很明顯這樣做,會讓ID為0的數據也無法回滾。為什么大家看我上面粘的MSDN解釋就知道了。

那么就這的話,答案會是什么呢,會不會有人想到是2,4,5呢。

想到2,4,5的人就錯了哦。因為當接受AcceptChanges()方法后,前面的0行就徹底刪除了,這時數據應該是1,2,3,4,5,然后RemoveAt(1)表示刪除第2行,刪除后也是立刻刪除的,無法回滾,所以這時數據應該是1,3,4,5,接着RemoveAt(2)刪除第3行,所以答案應該是1,3,5。
而原來把AcceptChanage()方法放在Delete()前面時,當調用tb.Rows[0].Delete()時,只是標記狀態為刪除,並沒有直接移除第0行,所以那個RemoveAt(1),還是從0,1,2,3,4,5中刪除第2行,所以答案是0,2,4,5。

好,我們再修改一下代碼:

tb.AcceptChanges();
tb.Rows[
0 ].Delete();            
tb.Rows.RemoveAt(
1 );
tb.AcceptChanges();
tb.Rows.RemoveAt(
2 );
tb.RejectChanges();

大家來猜猜答案是什么呢?

不知道有沒有人想到會是2,4,5,實際上不對。
正確的答案應該是2,3,5。

首先的第一個AcceptChanages表示將無法回滾前面添加數據的操作。接着第二個AcceptChanages表示徹底刪除Delete()所刪除的數據,這個時候數據就只剩下2,3,4,5了,然后再RemoveAt(2)把第三行刪除了,所以就剩下2,3,5了。

好的,我們再把第一個AcceptChanages()方法給刪除了,大家想想答案會是什么呢,代碼如下:

tb.Rows[ 0 ].Delete();            
tb.Rows.RemoveAt(
1 );
tb.AcceptChanges();
tb.Rows.RemoveAt(
2 );
tb.RejectChanges();

可能有人說了,AcceptChanages()方法是對前面的語句生效的,所以你把這個刪除了一點問題也沒有,答案當然還是2,3,5了,其實這種說法是錯誤的。

這段代碼的正確答案是1,3,5。
為什么會是這樣呢,那是因為當Delete()方法在前面沒有接收到AcceptChaages()方法后,會徹底刪除因為沒有必要回滾。所以RemoveAt(1)在執行時,實際上數據是1,2,3,4,5,它刪除第2行,也就是3。

好的,我們再看看下面的這段代碼:

tb.Rows[ 0 ].Delete();            
tb.Rows.RemoveAt(
1 );
tb.Rows.RemoveAt(
2 );
tb.AcceptChanges();
tb.RejectChanges();


不知道有沒有人會笑話我,實際上這段代碼和上面的代碼是一個效果哦。

那么我們再看看這段代碼呢?

tb.Rows[ 0 ].Delete();            
tb.Rows.RemoveAt(
1 );
tb.Rows.RemoveAt(
2 );
tb.RejectChanges();


我們把所有的AcceptChanges()方法都給去掉了,那么只剩下RejectChanages()方法了,會是什么樣的結果呢?
結果返回空記錄了,為什么呢????

其實在前面最早是無已經給出定義了,不知道的同學是太粗心了哦。自己去看哦。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM