2009-02-23 32 views
6

Ngoài câu hỏi này: Preorder tree traversal copy folder Tôi đã tự hỏi liệu có thể tạo một giao dịch có chứa các lệnh gọi khác nhau đến cơ sở dữ liệu hay không.Giao dịch trong C#

ví dụ:

public bool CopyNode(int nodeId, int parentNode) 
    { 
     // Begin transaction. 
     try 
     { 
      Method1(nodeId); 
      Method2(nodeId, parentNode); 
      Method3(nodeId); 
     } 
     catch (System.Exception ex) 
     { 
      //rollback all the methods 
     } 
    } 

Tôi không biết nếu điều này là có thể. Chúng tôi đang sử dụng subsonic để thực hiện các cuộc gọi cơ sở dữ liệu. Điều này thực sự quan trọng, không chỉ đối với vấn đề đi qua cây mà còn đối với một số nội dung khác mà chúng tôi thực hiện.

Ý tưởng chính là chúng tôi không thể để cơ sở dữ liệu của mình bị hỏng với dữ liệu chưa hoàn chỉnh.

Trả lời

3

Đó là có thể, bạn có thể tìm thấy một ví dụ here

Hoặc có lẽ một phạm vi giao dịch ...

http://msdn.microsoft.com/en-us/library/ms172152.aspx

+1

Oh xin lỗi, sau đó, có lẽ là một phạm vi giao dịch sẽ giúp đỡ, tôi không bao giờ làm việc với điều này, nhưng ở đây là liên kết: http://msdn.microsoft.com/en-us/library/ ms172152.aspx –

1

BeginTransaction được gọi tắt một đối tượng bộ sưu tập ADO.NET. Đối tượng Command cần giao dịch này (đối tượng SqlTransaction) được gán cho nó. Cam kết và Rollback chỉ được gọi trong phương thức bên ngoài.

Kiểm tra mã này. Nó hoạt động bằng cách tái sử dụng các đối tượng SqlConnection và SqlTransaction. Đây là một Master cổ điển> Loại chi tiết của thiết lập. Các loại bậc thầy là ColumnHeaderSet chứa một tài sản của

List<ColumnHeader>

, đó là chi tiết (bộ sưu tập).

Hy vọng điều này sẽ hữu ích. -JM

public static int SaveColumnHeaderSet(ColumnHeaderSet set) 
     //save a ColumnHeaderSet 
     {  
     string sp = ColumnSP.usp_ColumnSet_C.ToString(); //name of sp we're using 
     SqlCommand cmd = null; 
     SqlTransaction trans = null; 
     SqlConnection conn = null; 

     try 
     { 
      conn = SavedRptDAL.GetSavedRptConn(); //get conn for the app's connString 
      cmd = new SqlCommand(sp, conn); 
      cmd.CommandType = CommandType.StoredProcedure; 
      conn.Open(); 
      trans = conn.BeginTransaction(); 
      cmd.Transaction = trans; // Includes this cmd as part of the trans 

      //parameters 
      cmd.Parameters.AddWithValue("@ColSetName", set.ColSetName); 
      cmd.Parameters.AddWithValue("@DefaultSet", 0); 
      cmd.Parameters.AddWithValue("@ID_Author", set.Author.UserID); 
      cmd.Parameters.AddWithValue("@IsAnonymous", set.IsAnonymous);   
      cmd.Parameters.AddWithValue("@ClientNum", set.Author.ClientNum); 
      cmd.Parameters.AddWithValue("@ShareLevel", set.ShareLevel); 
      cmd.Parameters.AddWithValue("@ID_Type", set.Type); 

      //add output parameter - to return new record identity 
      SqlParameter prm = new SqlParameter(); 
      prm.ParameterName = "@ID_ColSet"; 
      prm.SqlDbType = SqlDbType.Int; 
      prm.Direction = ParameterDirection.Output; 
      cmd.Parameters.Add(prm); 

      cmd.ExecuteNonQuery(); 
      int i = Int32.Parse(cmd.Parameters["@ID_ColSet"].Value.ToString()); 
      if (i == 0) throw new Exception("Failed to save ColumnHeaderSet"); 
      set.ColSetID = i; //update the object 

      //save the ColumnHeaderList (SetDetail) 
      if (ColumnHeader_Data.SaveColumnHeaderList(set, conn, trans)==false) throw new Exception("Failed to save ColumnHeaderList"); 
      trans.Commit(); 

      // return ID for new ColHdrSet 
      return i; 
     } 
     catch (Exception e){ 
      trans.Rollback(); 
      throw e; 
     } 
     finally{ 
      conn.Close(); 
     } 
     } 

public static bool SaveColumnHeaderList(ColumnHeaderSet set, SqlConnection conn, SqlTransaction trans) 
     //save a (custom)ColHeaderList for a Named ColumnHeaderSet 
     { 
     // we're going to accept a SqlTransaction to maintain transactional integrity 
     string sp = ColumnSP.usp_ColumnList_C.ToString(); //name of sp we're using 
     SqlCommand cmd = null; 
     try 
     { 
      cmd = new SqlCommand(sp, conn);  // re-using the same conection object 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Transaction = trans;   // includes the cmd in the transaction 

      //build params collection (input) 
      cmd.Parameters.Add("@ID_ColSet", SqlDbType.Int); 
      cmd.Parameters.Add("@ID_ColHeader", SqlDbType.Int); 
      cmd.Parameters.Add("@Selected", SqlDbType.Bit); 
      cmd.Parameters.Add("@Position", SqlDbType.Int); 

      //add output parameter - to return new record identity 
      //FYI - @return_value = @ID_SavedRpt 
      SqlParameter prm = new SqlParameter(); 
      prm.ParameterName = "@ID"; 
      prm.SqlDbType = SqlDbType.Int; 
      prm.Direction = ParameterDirection.Output; 
      cmd.Parameters.Add(prm); 

      //Loop 
      foreach (ColumnHeader item in set.ColHeaderList) 
      { 
       //set param values 
       cmd.Parameters["@ID_ColSet"].Value = set.ColSetID; 
       cmd.Parameters["@ID_ColHeader"].Value = item.ColHeaderID; 
       cmd.Parameters["@Selected"].Value = item.Selected; 
       cmd.Parameters["@Position"].Value = item.Position; 

       cmd.ExecuteNonQuery(); 
       int i = Int32.Parse(cmd.Parameters["@ID"].Value.ToString()); 
       if (i == 0) throw new Exception("Failed to save ColumnHeaderSet"); 
      } 
      return true; 
     } 
     catch (Exception e) 
     { 
      throw e;    
     } 

     }