Linq to SQL - 撤销所有未提交的改动

在某些情况下我们需要撤销/丢弃所有未提交的改动,包括Update, Delete和Insert。context中GetChangeSet()方法可以返回当前所有未提交的改动,而我们的目标是清空Change Set。

撤销Update很简单,通过OverwriteCurrentValues的模式刷新,context中缓存的初始值以及改动后的对象都会被数据库中最新的值覆盖。

对于Insert,只要再调用一次DeleteOnSubmit的方法即可在ChangeSet中移除对象。

Delete则需要首先Refresh一次,然后InsertOnSubmit。

重要的是在这个过程中Linq to SQL会自动比较缓存的初始对象及更新后的对象,操作在内存中进行,并不会产生任何Insert/Update/Delete的数据库操作。

 

下面代码使用Extension Method将DiscardPendingChanges方法附加到DataContext对象中

    public static class DataContextExtensions
    {
        /// <summary>
        ///     Discard all pending changes of current DataContext.
        ///     All un-submitted changes, including insert/delete/modify will lost.
        /// </summary>
        /// <param name="context"></param>
        public static void DiscardPendingChanges(this DataContext context)
        {
            context.RefreshPendingChanges(RefreshMode.OverwriteCurrentValues);
            ChangeSet changeSet = context.GetChangeSet();
            if (changeSet != null)
            {
                //Undo inserts
                foreach (object objToInsert in changeSet.Inserts)
                {
                    context.GetTable(objToInsert.GetType()).DeleteOnSubmit(objToInsert);
                }
                //Undo deletes
                foreach (object objToDelete in changeSet.Deletes)
                {
                    context.GetTable(objToDelete.GetType()).InsertOnSubmit(objToDelete);
                }
            }
        }
 
        /// <summary>
        ///     Refreshes all pending Delete/Update entity objects of current DataContext according to the specified mode.
        ///     Nothing will do on Pending Insert entity objects.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="refreshMode">A value that specifies how optimistic concurrency conflicts are handled.</param>
        public static void RefreshPendingChanges(this DataContext context, RefreshMode refreshMode)
        {
            ChangeSet changeSet = context.GetChangeSet();
            if (changeSet != null)
            {
                context.Refresh(refreshMode, changeSet.Deletes);
                context.Refresh(refreshMode, changeSet.Updates);
            }
        }
    }

调用时:

    DataContext context = new DataContext();
    //Do insert/delete/update
    context.DiscardPendingChanges(); //Will clear DataContext.ChangeSet
    context.SubmitChanges();   //Nothing will be submit

 

posted on 2013-09-26 12:36  Teddy Li  阅读(1946)  评论(0编辑  收藏  举报