2009-11-12 89 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; 
      }