转:事务的使用(ADO.NET和SQL SERVER)
最近几天,在做项目的过程中,写了一些存储过程用来处理一些业务逻辑,发现在数据库中只有很少几个存储过程,而我这边就一个很小的模块都要涉及到几张表的操作,写存储过程是最方便的,而且效率也是最高的。于是,我问了一下这边的负责人,他们之前开发的那些模块,怎么没有写几个存储过程?而负责人的给我的回答是,以后别人来维护,出现问题时,跟踪调试写存储过程不好调试。我不敢苟同这种说法。
既然项目负责人不让用存储过程,那只能用代码实现这些业务逻辑了,我选择用ADO.NET中的事务。
我要实现的功能是上传附件的功能,需要涉及到3张表,分别是附件表Appendix,报告基础表Report和零件表Part。另外还有一张表示Appendix与Report的中间表StatusManage。上传附件时,需要向appendix表中插入一条附加信息记录,同时在页面可以修改Report表和Part表中的数据,表关系如下图
保存按钮中的代码如下:
/// <summary>
/// 上传附件保存事件
/// modify by dlw 2010-07-01
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void lbtnSave_Click(object sender, EventArgs e)
{
try
{
UpladFile();//这是将文件上传到服务器上的方法,可以不用考虑这个方法。//这是获取连接字符串的方法
string conStr = Common.CommonDB.CreateConnection().ConnectionString;
using (SqlConnection con = new SqlConnection(conStr))
{
con.Open();
SqlTransaction tran;//定义事务
SqlCommand com = con.CreateCommand();
tran = con.BeginTransaction();//创建事务
com.Transaction = tran;//为sqlcommand对象指定定义的事务
try
{
//插入一条新的附件记录
com.CommandText = string.Format(@"insert into dbo.PAB_Appendix (FlowID,[FileName],FilePath,FileRemark,UploadTime,Uploador)
values('{0}','{1}','{2}','{3}','{4}','{5}')",
ViewState["FlowID"].ToString(),
FileUpload.FileName,
AppDomain.CurrentDomain.BaseDirectory + "UploadFile//",
"",
DateTime.Now.ToString(),
User.Identity.Name
);
com.ExecuteNonQuery();
//更新pab基础表中的数据
com.CommandText = string.Format(@"update dbo.PAB_ReportList set CarType='{0}',Fachabteilung='{1}',
FOP_ID='{2}',FOP_Name='{3}',FactoryCode='{4}' where PAB_ReportID='{5}'",
ddlCarType.SelectedItem.Value.Trim(),//车型
ddlDept.SelectedItem.Value.Trim(),//科室
hiFop.Value,//fop
txtFOP.Text.Trim(),//
txtFactoryCode.Text.Trim(),//厂家
ViewState["PAB_ReportID"].ToString());
com.ExecuteNonQuery();
//更新主零件信息
com.CommandText = string.Format(@"update PAB_PartList set Part_Num='{0}' where PAB_PLID in
(select PAB_PartList.PAB_PLID from PAB_ReportList,PAB_PartList
where PAB_ReportList.PAB_ReportID=PAB_PartList.PAB_ReportID
and PAB_PartList.isMainPart=1
and PAB_ReportList.PAB_ReportID='{1}')",
txtMainPartNum.Text.Trim(),
ViewState["PAB_ReportID"].ToString());
com.ExecuteNonQuery();
tran.Commit();// 事务提交
Response.Write("<script>alert('上传成功!');returnValue=true;window.close();</script>");
}
catch (Exception ex)
{
tran.Rollback();//事务回滚
}
finally
{
tran.Dispose();//事务销毁
}
}
}
catch (Exception ex)
{
Response.Write("<script>alert('上传失败!')</script>");
}
}
上面的代码中,用红色标示出来的地方,是使用事务的地方。
总结一下,ADO.NET使用事务的格式是什么样子的呢? 把上面示例代码中用红色标示出来的代码提取出来,如下:
//这是获取连接字符串的方法
string conStr = Common.CommonDB.CreateConnection().ConnectionString;
using (SqlConnection con = new SqlConnection(conStr))
{
con.Open();
SqlTransaction tran;//定义事务
SqlCommand com = con.CreateCommand();
tran = con.BeginTransaction();//开始一个本地事务
com.Transaction = tran;//为sqlcommand对象指定定义的事务
try
{//TODO
//处理一些业务逻辑
tran.Commit();// 事务提交
}
catch (Exception ex)
{
tran.Rollback();//事务回滚
}
finally
{
tran.Dispose();//事务销毁
}
}
至此,用代码实现的业务逻辑就告一段落了。
刚开始的时候,我已经说过了,我已经用存储过程结合事务实现了上面的业务逻辑,下面把我用存储过程实现的业务逻辑给大家分享一下,希望对大家有一定的参考价值!
ALTER procedure [dbo].[SP_PAB_UploadAppendix]
(
@FileName varchar(50),--上传附件名称
@FilePath varchar(100),--上传附件路径
@FileRemark varchar(200),--附件备注
@Operator varchar(38),--操作人
@CarType varchar(10),--车型
@MainPartNum varchar(20),--主零件编号
@Fachabteilung varchar(10),--科室
@FOP_ID varchar(38),--负责人id
@FOP_Name varchar(50),--负责人名称
@FactoryCode Varchar(10),--厂家编号
@FactoryName Varchar(100),--厂家名称
@PAB_ReportID int,
@StatusID int --
)
as
begin
begin try
begin tran --事务开始
--获取与reportlist中status对应的flowid
declare @FlowID int
select @FlowID=PAB_StatusManage.FlowID from PAB_StatusManage
where PAB_ReportID=@PAB_ReportID and StatusID=@StatusID
--向附件表中插入数据
insert into dbo.PAB_Appendix (FlowID,[FileName],FilePath,FileRemark,UploadTime,Uploador)
values(@FlowID,@FileName,@FilePath,@FileRemark,getdate(),@Operator)
--更新reportlist表中的数据
update dbo.PAB_ReportList set CarType=@CarType,Fachabteilung=@Fachabteilung,
FOP_Name=@FOP_Name,FactoryCode=@FactoryCode where PAB_ReportID=@PAB_ReportID
--更新partlist表中主零件的数据
if exists(select 1 from PAB_ReportList,PAB_PartList where PAB_ReportList.PAB_ReportID=PAB_PartList.PAB_ReportID and PAB_PartList.isMainPart=1 and PAB_ReportList.PAB_ReportID=@PAB_ReportID)
begin
update PAB_PartList set Part_Num=@MainPartNum where PAB_PLID in
(select PAB_PartList.PAB_PLID from PAB_ReportList,PAB_PartList where PAB_ReportList.PAB_ReportID=PAB_PartList.PAB_ReportID and PAB_PartList.isMainPart=1 and PAB_ReportList.PAB_ReportID=@PAB_ReportID)
endcommit tran--事务提交
end try
begin catch
rollback tran--事务回滚
end catch
end
上面红色标出的地方是使用事务的地方。
总结一下,把红色部分代码提取出来,如下:
begin try
begin tran --事务开始
--处理一些业务逻辑
commit tran--事务提交
end try
begin catch
rollback tran--事务回滚
end catch
至此,两种方式都给大家贴示出来了,希望对大家有一定的帮助。