关于 try catch 里面加入数据库事务管理

shanliu 2009-07-24 02:29:51
try
{
con1.RunProc(" begin tran ");
。。。。
\\程序执行数据库修改
con1.RunProc(" insert into 。。。");
。。。。
con1.RunProc(" commit ");
}

catch (Exception ex)
{

con1.RunProc(" ROLLBACK ");

}

想实现这样的功能:我的 执行数据库修改在程序里涉及几个表,为了保证数据库的完整性以及有效性,我想让程序不出错时,可以顺利执行完毕,然后提交完成 con1.RunProc(" commit ");
。当程序运行错误时,提交数据库返回操作con1.RunProc(" ROLLBACK ");
我这样写的一直有报错出现,好像没有报错时con1.RunProc(" ROLLBACK ");也会运行,请高手指教。
public SqlCommand RunProc(string procName)
{
SqlConnection conn = this.getcon1();
SqlCommand cmd = conn.CreateCommand();
conn.Open();
cmd.CommandText = procName;
cmd.ExecuteNonQuery();
return cmd;
}
...全文
818 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
yutian_31 2009-07-24
  • 打赏
  • 举报
回复
我这有个发票的产生过程,应该和你说的一样:即发票的单头和单身,两个表必须同时成功插入或同时回滚
下面是代码 你参考下:

public string CreateInvoiceInfo(DataGrid DataGrid1, DateTime CreateDt)
{
string PreConfirmID = "", InvoiceNo = "";
DateTime InvoiceCreateDt = DateTime.Parse("1900-1-1");
SqlCommand command = new SqlCommand();
InitConn();
SqlTransaction myTrans = myConn.BeginTransaction();
try
{
Entity.IsSucceed = true;

command.Transaction=myTrans;
command.Connection=myConn;
command.CommandType = CommandType.StoredProcedure;

TextBox txtPrice = null;
for(int i = 0; i < DataGrid1.Items.Count; i ++)
{
PreConfirmID = DataGrid1.DataKeys[DataGrid1.Items[i].ItemIndex].ToString().Trim();
InvoiceCreateDt = CreateDt;
txtPrice = (TextBox)DataGrid1.Items[i].Cells[9].FindControl("txtUnitPrice");

if(InvoiceNo == "")//玻ネInvoiceNo, 玂Invoice Head
{
CreateInvoiceHeader(command, PreConfirmID, out InvoiceNo,InvoiceCreateDt);
}

CreateInvoiceDetailRecord(command, InvoiceNo, PreConfirmID, decimal.Parse(txtPrice.Text.Trim()));
}
if(InvoiceNo != "")
{
//эInvoice虫繷羆计秖
UpdateInvoiceHeader(command, InvoiceNo);
//玂Invoice Detail Old Price
SaveOldPriceByGRN(command, InvoiceNo, DataGrid1);
}
myTrans.Commit();
}
catch(Exception e)
{
myTrans.Rollback();
Entity.IsSucceed = false;
Entity.Message = e.Message;
}
finally
{
myConn.Close();
}
return InvoiceNo;
}
大狼尾巴 2009-07-24
  • 打赏
  • 举报
回复
把我多表保存的一段代码给楼主参考一下。。。


using (SqlConnection conn = new SqlConnection(global::cxifrmwk_cs.Properties.Settings.Default.cxiHis2008ConnectionString))
{
SqlTransaction tx = null;

App_Data.DsKfInfoTableAdapters.kf_ckxx_zbTableAdapter taZb = null;
App_Data.DsKfInfoTableAdapters.kf_ckxx_mxTableAdapter taMx = null;

try
{
taZb = new cxifrmwk_cs.App_Data.DsKfInfoTableAdapters.kf_ckxx_zbTableAdapter();
taMx = new cxifrmwk_cs.App_Data.DsKfInfoTableAdapters.kf_ckxx_mxTableAdapter();

/*------------- 保存 -----------------------------------------------------*/
conn.Open();

tx = conn.BeginTransaction("KF_CKCL");

taZb.Connection = conn;
taMx.Connection = conn;

taZb.setTransaction(tx);
taMx.setTransaction(tx);

taZb.Update(_dtCkzb);
taMx.Update(_dtCkmx);

tx.Commit();

this.BillNo = sCkdh;
this.BillOperateStatus = BillOperateStatus.Modify;

taZb.FillByCkdh(_dtCkzb, this.BillNo);
taMx.FillByCkdh(_dtCkmx, this.BillNo);

this.v_kf_ckzbTableAdapter.FillByCkdh(this.dsKfInfo.v_kf_ckzb, sCkdh);
this.v_kf_ckmxTableAdapter.FillByCkdh(this.dsKfInfo.v_kf_ckmx, sCkdh);

this.v_kf_ckzbBindingSource.MoveLast();

this.dgvMx.Refresh();

this.__dg = DialogResult.Yes;

cxi_util.alert("保存成功!");

}
catch (DBConcurrencyException dbex)
{
if (tx != null)
tx.Rollback();

_dtCkzb.RejectChanges();
_dtCkmx.RejectChanges();

cxi_util.alert("更新数据时发生错误,可能该出库单已在别处被更改!\n\n" + dbex.Message);
}
catch (Exception ex)
{
if (tx != null)
{
tx.Rollback();
}

_dtCkzb.RejectChanges();
_dtCkmx.RejectChanges();

throw new Exception(ex.Message);
}
}
xkx2003 2009-07-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 shanliu 的回复:]
可能是我没有说清楚;我是在保存按钮上的程序,保存时,我同时保存到两个表里面,所以con1.RunProc(" insert into 。。。");
要用两次,我想把这两次修改的数据,作为一个事物,要修改两个表都修改,要修改失败,两个表都失败。
ps:
private void button4_Click(object sender, EventArgs e)
        {
            try
            {
            con1.RunProc(" begin tran ");
              con1.RunProc(" commit ");
            }

            catch (Exception ex)
            {

                con1.RunProc(" ROLLBACK ");
                MessageBox.Show(ex.Message, "保存错误,请联系信息系统管理员", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
我变成这样调试,也是错误的,奇怪的是  ROLLBACK 提交到数据库了  但是MessageBox并没有出报错数据。

[/Quote]
一个conn,生成两个command,
try
{
然后去操作两个表,
Transaction.commit
}
catch
{
Transaction.rollback
}
tangyong12 2009-07-24
  • 打赏
  • 举报
回复
3楼的写法是最正确的,将数据库连接的open以及起始事物都应放在try前面,否则连接没打开的时候遇到catch里的回滚会报错,建议方式:
1、三楼的写法
2、con1.Open();
con1.RunProc(" begin tran "); //如果不把这句放在try外面,在下面一旦遇到还没开始事务就报错的时候会有问题
try
{
con1.RunProc(" commit ");
}
catch (Exception err)
{
con1.RunProc(" ROLLBACK ");
throw err;
}
anguslaigz 2009-07-24
  • 打赏
  • 举报
回复
OleDbConnection cn;
OleDbCommand cmd = new OleDbCommand();
OleDbTransaction oletran = null;
cn = new OleDbConnection(db.ConnStr());
cn.Open();
oletran = cn.BeginTransaction(IsolationLevel.ReadCommitted);
cmd.Connection = cn;
cmd.Transaction = oletran;
string ls_Insert = "begin InsertProcude('01','" + "02" + ");end;";
try
{
cmd.CommandText = ls_Insert;
cmd.ExecuteNonQuery();
oletran.Commit();
}
catch (Exception er)
{

oletran.Rollback();
}
mbh0210 2009-07-24
  • 打赏
  • 举报
回复
OleDbTransaction tran = _conn.BeginTransaction();
string sql = "";
OleDbCommand Command = new OleDbCommand(sql, _conn);
Command.Transaction = tran;
mbh0210 2009-07-24
  • 打赏
  • 举报
回复
没有必须用Sql语句写事务,
直接用OleDbTransaction对象,出现异常,用OleDbTransaction对象的Rollback函数就可以了
shanliu 2009-07-24
  • 打赏
  • 举报
回复
可能是我没有说清楚;我是在保存按钮上的程序,保存时,我同时保存到两个表里面,所以con1.RunProc(" insert into 。。。");
要用两次,我想把这两次修改的数据,作为一个事物,要修改两个表都修改,要修改失败,两个表都失败。
ps:
private void button4_Click(object sender, EventArgs e)
{
try
{
con1.RunProc(" begin tran ");
con1.RunProc(" commit ");
}

catch (Exception ex)
{

con1.RunProc(" ROLLBACK ");
MessageBox.Show(ex.Message, "保存错误,请联系信息系统管理员", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
我变成这样调试,也是错误的,奇怪的是 ROLLBACK 提交到数据库了 但是MessageBox并没有出报错数据。
hecker728 2009-07-24
  • 打赏
  • 举报
回复

catch(Exception ex)
{
trans.Rollback();
}

net105 2009-07-24
  • 打赏
  • 举报
回复
con1.Open();
try
{
con1.RunProc(" begin tran ");
//程序执行数据库修改
con1.RunProc(" insert into 。。。");
。。。。
.RunProc(" commit ");
}
catch (Exception ex)
{
con1.RunProc(" ROLLBACK ");
}
finally
{
con1.Close();
}
beackoom 2009-07-24
  • 打赏
  • 举报
回复
每次执行完了之后conn.Close();
云孤天 2009-07-24
  • 打赏
  • 举报
回复

private void button4_Click(object sender, EventArgs e)
{
try
{
con1.Open();
con1.RunProc(" begin tran ");
//程序执行数据库修改
con1.RunProc(" insert into 。。。");
。。。。
con1.RunProc(" commit ");
con1.Close();
}

catch (Exception ex)
{

con1.RunProc(" ROLLBACK ");
con1.Close();

}
}
public SqlCommand RunProc(string procName)
{
SqlConnection conn = this.getcon1();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = procName;
cmd.ExecuteNonQuery();
return cmd;
}
cpp2017 2009-07-24
  • 打赏
  • 举报
回复
1.ado.net中有Transactoin对象,没有必须在sql中做
2.如果执行了 con1.RunProc(" ROLLBACK ");
那说明肯定出现了错误,你可在这里设个断点跟踪一下。
acqy 2009-07-24
  • 打赏
  • 举报
回复
没必要在数据库端执行transaction吧?

using (DbTransaction trans = con1.BeginTransaction())
{
try
{
//..
trans.Commit();
}
catch
{
trans.Rollback();
}
}
cadtian 2009-07-24
  • 打赏
  • 举报
回复
我也想知道catch中都可以写一些什么。做一些啥操作?
关注中
云孤天 2009-07-24
  • 打赏
  • 举报
回复
conn.Open();
如果每次调用RunProc而没有关闭,那当然会报错啊。

没必要每次都Open一下吧?

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧