簡體   English   中英

在一個ado.net事務中執行多個語句/ sqlcomands

[英]Executing multiple statements / sqlcomands within a single ado.net transaction

我這里不包含任何代碼,因為在過去的幾天里我已經重寫了很多次了,它的確再也不值得麻煩了,所以我將用通用術語來解釋我的問題。

我有一個用C#編寫並連接到sql服務器數據庫的winforms應用程序。 在我的應用程序的某些部分中,我可以對數據庫中的多個表執行多達10條SQL命令,並且我需要將其包含在一個事務中,因為這是“全有還是全無”的情況。 如果10個命令中的任何一個失敗,我都希望不提交任何命令。

復雜的因素包括:

  1. 10個sqlcommand中的每一個都有多個參數
  2. 一些sqlcommand使用INSERT,我需要在隨后的一些sqlcommand中使用服務器生成的標識。
  3. 一些命令對相同的數據進行操作,即,較早的命令可能會在數據庫中插入新項,而較晚的sqlcommand之一將嘗試更新該相同條目。

非常感謝您的幫助,因為本周大部分時間都在忙於解決這個問題,因此我感覺進展很少。

編輯:

sqlcommand最初位於不同的類中,但是我雖然可能是問題所在,所以我做了很大的重寫,現在所有的sqlcommand都在同一方法內,盡管有些sqlcommand寫在其他地方並傳遞回了主要方法。

當前的問題是,執行了第一個命令(INSERT),但是事務在第二個命令處失敗,因為該事務試圖引用在第一個命令中創建的數據庫條目。

我也不能使用TransactionScope,因為網絡上的MSDTC會引起其他問題,因此我需要使用我的應用程序和ADO.NET來處理。

編輯(某些代碼)

這只是事務中的前兩個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...//

問題

sqlSaveCase命令在tblCases上插入一個新的案例,但是當第二個命令sqlNewIPLink嘗試使用由第一個創建的Identity時,它將生成一個外鍵錯誤,好像沒有從第一個命令看到新創建的Case一樣。

錯誤是這條線

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

應該使用ExecutreScalar()才能從INSERT命令中檢索ID。 當我最終意識到它總是返回1時,線索就出現了,我認為這可能只是一個布爾“真”來表示命令已執行。 當我在命令上使用ExecuteScalar時,它開始返回更有意義的ID,隨后的SqlCommands可以識別這些ID,因此沒有Foregin Key問題。

不確定這是否是問題,但我看不到您在第二個SqlCommand上使用c.SetCaseNo的位置。

  //
  // 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();   

您可以使用TransactionScope類。

是對它的很好的解釋。

希望這可以幫助。

在您的情況下,使用命令模式是一個好習慣。 實際上,它允許您撤消操作。 事務對於很少的操作來說是有好處的,但是使用10個操作,最好在循環中執行每個命令,如果一個命令失敗,則撤消命令。 這意味着您要執行回滾操作(此處為10)。 這里是模式樣本鏈接:http://www.dofactory.com/Patterns/PatternCommand.aspx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM