2012-07-28 100 views
0

我在這裏沒有包含任何代碼,因爲在過去的幾天裏我已經重寫了很多次,真的不值得再打擾,所以我用通用術語解釋我的問題。在單個ado.net事務中執行多個語句/ sqlco命令

我有一個用C#編寫的並連接到sql server數據庫的winforms應用程序。在我的應用程序的某些部分,我可以在數據庫中的許多表上運行多達10條SQL命令,並且我需要在單個事務中包含這些SQL命令,因爲它是「全部或全部」情況。如果10個命令中的任何一個失敗,我希望不提交這些命令。

複雜的因素包括:

  1. 每個10個sqlcommands的具有多個參數
  2. 一些sqlcommands的使用INSERT和我需要使用服務器生成的身份在一些後續的sqlcommands。
  3. 某些命令對相同數據進行操作,即早期命令可能會在數據庫中插入一個新項目,而後面的一個sqlcommands將嘗試更新該項目。

任何幫助將是最受讚賞,因爲我在我的智慧結束這個問題花了大部分時間在這個問題上,而且感覺只有相對較小的進展。

編輯:

的sqlcommands原本在不同的班級等,但是我雖然是可能,所以我做了一個很大的重寫是問題,現在所有的sqlcommands的是相同的方法中,儘管一些sqlcommands被寫入其他地方並傳遞迴主方法。

現在的問題是執行第一個命令(INSERT),但是事務在第二個命令上失敗,因爲那個嘗試引用在第一個命令中創建的數據庫條目。

此外,我不能使用TransactionScope,因爲網絡上的MSDTC導致其他問題,所以我需要處理這與我的應用程序和ADO.NET。

EDIT(一些代碼)

這裏只是在事務內的前兩個sqlcommands:

string connectionString = aSystem.ConnectionString; 

    using (SqlConnection linkToDB = new SqlConnection(connectionString)) 
    { 
     linkToDB.Open(); 
     using (SqlTransaction transaction = linkToDB.BeginTransaction()) 
     { 
      try 
      {        
       //...Case...// 

       cCase c = new cCase(); 
       c.CaseType = cboCaseType.Text; 
       c.Occupation = txtOccupation.Text; 
       c.DateInstructed = txtDateInst.Text; 
       c.Status = "Live"; 
       SqlCommand sqlSaveCase = c.SaveSqlCom();        
       sqlSaveCase.Connection = linkToDB; 
       sqlSaveCase.Transaction = transaction; 
       c.SetCaseNo = sqlSaveCase.ExecuteNonQuery().ToString(); 

       //...IP Link...// 

       string strIPID = cboIPAddress.SelectedValue.ToString(); 
       SqlCommand sqlNewIPLink = cIPID.NewIPLinkSqlCom(strIPID,c.CaseNo,txtIPRef.Text); 
       sqlNewIPLink.Connection = linkToDB; 
       sqlNewIPLink.Transaction = transaction; 
       sqlNewIPLink.ExecuteNonQuery();    //...fails here...// 


       //...an additional 8 sql commands follow...// 

ISSUE

的sqlSaveCase命令插入上tblCases一個新的情況下,但是,當第二命令sqlNewIPLink嘗試使用由第一個命令創建的Identity,它會生成一個外鍵錯誤,就好像它沒有從第一個命令中看到新創建的Case一樣。

+0

10個命令是否在代碼的不同位置。即不同的類,實例等? – devundef 2012-07-28 09:03:04

+0

究竟是什麼,你有麻煩? – Andreas 2012-07-28 09:04:46

+0

真的不清楚你的問題究竟在哪裏。爲什麼你不能使用'SqlTransaction'?也許可以嘗試將它分解爲更多的問題,每個問題都可以通過一個簡單的*代碼示例輕鬆地展現出* *特定的問題。 – 2012-07-28 09:18:00

回答

2

錯誤爲這條線

c.SetCaseNo = sqlSaveCase.ExecuteNonQuery().ToString(); 

應以檢索來自INSERT命令的ID使用ExecutreScalar()。當我最終意識到它總是返回1時,線索出現了,我認爲這可能僅僅是一個布爾'真'來表示命令被執行。一旦我在命令上使用了ExecuteScalar,它就開始返回更多有意義的ID,後面的SqlCommands可以識別,因此沒有Foregin Key問題。

0

您可以使用TransactionScope類。

here是很好的解釋。

希望這有助於。

+0

不能在網絡上使用MSDTC – PJW 2012-07-28 09:15:25

0

在你的情況下,使用命令模式是一種很好的做法。事實上,它可以讓你撤銷你的操作。對於少數操作,事務是有效的。但是對於10個操作,最好在循環中執行每個命令,並且如果一個命令失敗,則使用undo命令。這意味着你實現了回滾操作(這裏是10)。 這裏有一個模式樣本的鏈接:http://www.dofactory.com/Patterns/PatternCommand.aspx

1

不知道是否這是問題,但我沒有看到你在哪裏使用c.SetCaseNo在第二個SqlCommand上。

// 
    // here you are setting c.SetCaseNo 
    // 
    c.SetCaseNo = sqlSaveCase.ExecuteNonQuery().ToString(); 

    string strIPID = cboIPAddress.SelectedValue.ToString(); 

    // 
    // but here you're using c.CaseNo 
    // 
    SqlCommand sqlNewIPLink = cIPID.NewIPLinkSqlCom(strIPID,c.CaseNo,txtIPRef.Text); 


    sqlNewIPLink.Connection = linkToDB; 
    sqlNewIPLink.Transaction = transaction; 
    sqlNewIPLink.ExecuteNonQuery(); 
+0

感謝您的支持 - 只發布了ExecuteNonQuery而不是ExecuteScalar的答案。 SetNewCase是CaseNo的第二個訪問修飾符,繞過了我的類中內置的驗證。 – PJW 2012-07-28 10:30:56