i have this procedure for inserting rows in tables(sql server 2005)
CREATE PROCEDURE ans_insert
(
@q_desc varchar(2000),
@sub_id int,
@marks int,
@ans1 varchar(1000),
@ans varchar(1000),
@userid varchar(15),
@cr_date datetime
)
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
DECLARE @q_id int
insert into questions(q_desc,sub_id,marks,created_by,DT_created) values(@q_desc,@sub_id,@marks,@userid,@cr_date);
SET @q_id = IDENT_CURRENT('questions')
INSERT INTO answers(ans_desc,q_id,created_by,DT_created,istrue)
VALUES( @ans1,@q_id,@userid,@cr_date,
CASE WHEN @ans1 =@ans THEN 1 ELSE 0 END);
COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
DECLARE @ErrorLine INT;
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorLine=ERROR_LINE(),
@ErrorState = ERROR_STATE();
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState,@ErrorLine);
END CATCH
END
我从我的ASP.NET表单中将其称为
在添加所有参数后,AnsCmd是我的存储过程命令
try
{
conn.Open();
AnsCmd.ExecuteNonQuery();
lblMsg.Visible = true;
lblMsg.Text = "success";
conn.Close();
}
catch (SqlException sqlex)
{
lblMsg.Visible = true;
lblMsg.Text = sqlex.ToString();
}
catch (Exception ex)
{
lblMsg.Visible = true;
lblMsg.Text = ex.ToString();
}
检查raiserror是否正常工作,我将插入中的表名更改为答案1的答案1,但不存在..
执行时我收到错误消息
System.Data.SqlClient.SqlException:无效的对象名称'answers1'。 EXECUTE之后的事务计数表示缺少COMMIT或ROLLBACK TRANSACTION语句。 System.Data.SqlClient.SqlConnection.OnError(SqlException异常,......
以前的count = 0,当前计数= 1这件事情也正常,或者我错过了什么?
答案 0 :(得分:2)
批处理(存储过程)在到达不存在的表(deferred name resolution)时正在中止,因此ROLLBACK没有执行。
来自MSDN/BOL:
编译和声明级重新编译错误
有两种类型的错误 不会被TRY ... CATCH处理 错误发生在同一个执行中 等级为TRY ... CATCH构造:
- 编译错误,例如阻止批处理的语法错误 执行。
- 语句级重新编译期间发生的错误,例如 对象名称解析错误 由于编译后发生 延期名称解析。
批处理,存储过程或 包含TRY ... CATCH的触发器 构造生成其中之一 错误,TRY ... CATCH构造确实如此 不处理这些错误。
我建议你在顶部添加SET XACT_ABORT ON
。这会强制ROLLBACK
出现错误并“整理”。
还有一件事......
SET @q_id = IDENT_CURRENT('questions')
应该是
SET @q_id = SCOPE_IDENTITY()
编辑:
CREATE PROCEDURE ans_insert
@q_desc varchar(2000),
@sub_id int,
@marks int,
@ans1 varchar(1000),
@ans varchar(1000),
@userid varchar(15),
@cr_date datetime
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON; -- what I do
BEGIN TRY
....
答案 1 :(得分:0)
我认为它不会影响异常 - 但有些想法:
SCOPE_IDENTITY()
会比IDENT_CURRENT
更容易(也更可靠)吗? IDENT_CURRENT
可以在并行操作期间从另一个会话返回ID。同时避免@@IDENTITY
,这可能会受到INSERT
s SqlTransaction
)或更宽(TransactionScope
)示例SqlTransaction
方法:
using(SqlTransaction tran = conn.BeginTransaction()) {
try {
// operations (may need to set command.Transaction = tran)
tran.Commit();
} catch {
tran.Rollback();
throw;
}
}
示例TransactionScope
方法(**必须SPAN连接**)
using(TransactionScope tran = new TransactionScope()) {
// operations: note no other changes
tran.Complete();
}