C# 在单个ado.net事务中执行多个语句/sqlcomands
我这里不包括任何代码,因为在过去几天里我已经写了很多次了,实在不值得再费心了,所以我将用一般术语解释我的问题 我有一个用C#编写的winforms应用程序,并连接到sql server数据库。在我的应用程序的某些部分中,我可以在数据库中的许多表上运行多达10个SQL命令,并且我需要在单个事务中包含这些SQL命令,因为这是一种“要么全有,要么全无”的情况。如果10个命令中的任何一个失败,我希望不提交任何一个命令 复杂因素包括:C# 在单个ado.net事务中执行多个语句/sqlcomands,c#,winforms,ado.net,transactions,sqlcommand,C#,Winforms,Ado.net,Transactions,Sqlcommand,我这里不包括任何代码,因为在过去几天里我已经写了很多次了,实在不值得再费心了,所以我将用一般术语解释我的问题 我有一个用C#编写的winforms应用程序,并连接到sql server数据库。在我的应用程序的某些部分中,我可以在数据库中的许多表上运行多达10个SQL命令,并且我需要在单个事务中包含这些SQL命令,因为这是一种“要么全有,要么全无”的情况。如果10个命令中的任何一个失败,我希望不提交任何一个命令 复杂因素包括: 10个SQLCommand中的每一个都有多个参数 一些sqlcomma
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尝试使用第一个命令创建的标识时,它会生成一个外键错误,就好像它没有从第一个命令中看到新创建的案例一样。您可以使用TransactionScope类 这是很好的解释
希望这对您有所帮助。您可以使用TransactionScope类 这是很好的解释
希望这能有所帮助。在您的情况下,使用命令模式是一种很好的做法。事实上,它允许您撤消操作。事务只适用于少数操作。但对于10个操作,最好在循环中执行每个命令,如果一个命令失败,则执行undo命令。这意味着您要实现回滚操作(这里是10)。
这里有一个与模式示例的链接:http://www.dofactory.com/Patterns/PatternCommand.aspx在您的案例中,使用命令模式是一个很好的实践。事实上,它允许您撤消操作。事务只适用于少数操作。但对于10个操作,最好在循环中执行每个命令,如果一个命令失败,则执行undo命令。这意味着您要实现回滚操作(这里是10)。
这里有一个与模式示例的链接:http://www.dofactory.com/Patterns/PatternCommand.aspx不确定这是否是问题所在,但我看不出在第二个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();
不确定这是否是问题所在,但我不知道在第二个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();
错误就在这一行
c.SetCaseNo = sqlSaveCase.ExecuteNonQuery().ToString();
应该使用ExecutreScalar()从INSERT命令检索ID。当我最终意识到它总是返回1时,我想这可能只是一个布尔值“true”,表示命令已执行。我在命令上使用ExecuteScalar后,它开始返回更多有意义的ID,后续SqlCommands无法识别这些ID,因此没有Foregin键问题。错误是这一行
c.SetCaseNo = sqlSaveCase.ExecuteNonQuery().ToString();
应该使用ExecutreScalar()从INSERT命令检索ID。当我最终意识到它总是返回1时,我想这可能只是一个布尔值“true”,表示命令已执行。一旦我在命令上使用了ExecuteScalar,它就开始返回更有意义的ID,后续的SqlCommands没有识别这些ID,因此没有Foregin关键问题。是代码中不同位置的10个命令。i、 不同的类、实例等?你到底有什么问题?你到底有什么问题还不清楚。为什么不能使用
SqlTransaction
?也许可以试着把这个问题分成更多的问题,每个问题处理一个可以通过简单的代码示例轻松演示的特定问题。您的示例代码实际上是有效的(尽管您似乎有设计问题)。什么东西不起作用?sqlSaveCase命令在tblCases上插入一个新的案例,但当第二个命令sqlNewIPLink尝试使用第一个命令创建的标识时,它会生成一个外键错误,好像它没有从第一个命令中看到新创建的案例。这10个命令在代码中的不同位置。i、 不同的类、实例等?你到底有什么问题?你到底有什么问题还不清楚。为什么不能使用SqlTransaction
?也许可以试着把这个问题分成更多的问题,每个问题处理一个可以通过简单的代码示例轻松演示的特定问题。您的示例代码实际上是有效的(尽管您似乎有设计问题)。什么是不起作用的?sqlSaveCase命令在tblCases上插入一个新的案例,但是当第二个命令sqlNewIPLink尝试使用第一个命令创建的标识时,它会生成一个外键错误,就好像它没有从第一个命令中看到新创建的案例一样。谢谢-刚刚发布了答案