2009-11-12 86 views
7

我想創建一個C#應用程序,在其中複製兩個不同文件夾(已包含舊版本文件)中的一些文件並運行SQL腳本。在整個過程中,如果產生任何異常,我需要回滾所有更改。如何實現回滾功能?

對於sql腳本,可以使用轉換,但是如何使用回滾實現文件複製過程?

+0

根據您指定的系統上,文件系統的變化也可以放在一個事務。從Windows Vista開始,NTFS具有此功能。 – Joey 2009-11-12 07:47:38

回答

2

在替換之前,您可以從舊文件複製一份,然後如果發生異常,則從此複製恢復。

0

它適合您的使用情況將文件複製到臨時目錄,然後將整個目錄移動到位?如果是這樣,回滾就像刪除臨時目錄一樣簡單。

+1

如果該目錄的移動操作失敗,你會怎麼做?這幾乎不是原子操作,所以它*可能*失敗。 – Joey 2009-11-12 07:58:25

+0

此舉實際上是大多數操作系統中的重命名。它發生在一個單一的操作。操作系統在更改期間鎖定表示目錄的文件,以便它像原子一樣工作。查看Linux'mv'命令的這個古代手冊中提供的保證:http://www.linuxmanpages.com/man2/rename.2.php – 2009-11-12 10:17:46

3

如果可能,您可以利用Transactional NTFS。如果沒有,那麼你可以保留你所做的操作列表,並在需要回滾時做相反的操作。

3

或者您可以發展爲軟件開發人員並使用Command Pattern並實現BatchCommand。通過命令可以非常容易地添加撤消功能並以智能方式進行封裝。然後BatchCommand可以在其列表中的每個Command上調用undo()。

對於一個好的底漆模式,看看Head First Design Patterns

0

我會複製到新的文件追加後綴和一個隨機數,從而避免與已經存在的文件名衝突。

示例... 舊文件=「myfile.txt」,新文件=「myfile.txt.new.285387」。

然後,當複製過程完成後,我會... - 將舊文件的名稱標記爲「myfile.txt.old.3464353」。 - 將新文件命名爲「myfile.txt」 - 最後將刪除舊的文件。

0

試試這個代碼

public bool updateusertable(string UserName,string Password,string Datetime) 
      { 
       bool bResult = false;    
      SqlTransaction tx; 
       try 
       { 
        tx=conn.Begintransaction(); 
        SqlCommand Ocmd = new SqlCommand(); 
        Sqlconnect = Cconnect.OpenSqlConnection(); 
        Ocmd.Connection = Sqlconnect; 
        Ocmd.CommandType = CommandType.StoredProcedure; 
        Ocmd.CommandText = "SP_User_login_Update"; 
        Ocmd.Parameters.Add("@UserName", SqlDbType.VarChar, 100).Value = UserName; 
        Ocmd.Parameters.Add("@Password", SqlDbType.VarChar, 100).Value = Password; 
        Ocmd.Parameters.Add("@lastlogin", SqlDbType.VarChar, 100).Value = Datetime; 
        int i = Ocmd.ExecuteNonQuery(); 
        if (i <= 1) 
        { 
         bResult = true; 
         tx.Commit(); 
        }else 
        { 
         tx.Rollback(); 
        } 
       } 
       catch (Exception ex) 
       { 
        string msg = ex.Message.ToString(); 
        tx.Rollback(); 
       } 
       finally 
       { 

       } 
       return bResult; 
      }