![](/img/trans.png)
[英]ado.net - is putting a single SQL statement through a connection better than equivalent multiple SQL statements?
[英]Executing multiple statements / sqlcomands within a single ado.net transaction
我這里不包含任何代碼,因為在過去的幾天里我已經重寫了很多次了,它的確再也不值得麻煩了,所以我將用通用術語來解釋我的問題。
我有一個用C#編寫並連接到sql服務器數據庫的winforms應用程序。 在我的應用程序的某些部分中,我可以對數據庫中的多個表執行多達10條SQL命令,並且我需要將其包含在一個事務中,因為這是“全有還是全無”的情況。 如果10個命令中的任何一個失敗,我都希望不提交任何命令。
復雜的因素包括:
非常感謝您的幫助,因為本周大部分時間都在忙於解決這個問題,因此我感覺進展很少。
編輯:
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();
在您的情況下,使用命令模式是一個好習慣。 實際上,它允許您撤消操作。 事務對於很少的操作來說是有好處的,但是使用10個操作,最好在循環中執行每個命令,如果一個命令失敗,則撤消命令。 這意味着您要執行回滾操作(此處為10)。 這里是模式樣本鏈接:http://www.dofactory.com/Patterns/PatternCommand.aspx
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.