我在我的代码中发现了一个错误,我对它最初是如何发生的事感到困惑。
我的问题是,我在数据库ID字段中发现了一个跳过(它是一个递增的标识字段),表示没有插入一些记录 - 这意味着我的SQL sprocs(可能)引发了错误。从那里向后思考,这意味着我的业务对象应该已经捕获了该错误并将其抛出,立即退出并返回到页面的代码隐藏(而是继续直接进入第二个存储过程)。我不明白为什么或如何做到这一点。关于代码执行跳过我的尝试捕获的事情发生了什么?
页面代码背后:
protected void submitbutton_click(object sender, EventArgs e){
try{
mybusinessobject.savetodatabase()
} catch( Exception ex) {
Response.Redirect("Error.aspx");
}
}
业务对象代码:
public static void savetodatabase(){
int ID1=-1;
int ID2=-1;
//store the billing contact
SqlCommand cmd1 = new SqlCommand("SaveInfo1", con);
cmd1.CommandType = CommandType.StoredProcedure;
//...
cmd1.Parameters.Add("@Ret", SqlDbType.Int);
cmd1.Parameters["@Ret"].Direction = ParameterDirection.ReturnValue;
try
{
con.Open();
cmd1 .ExecuteNonQuery();
ID1 = Convert.ToInt32(cmd1.Parameters["@Ret"].Value);
}
catch (Exception ex) { throw ex; }
finally { con.Close(); }
if (ID1 > 0)
{
SqlCommand cmd = new SqlCommand("SaveInfo2", con);
cmd.CommandType = CommandType.StoredProcedure;
//...
try
{
con.Open();
cmd.ExecuteNonQuery();
ID2= Convert.ToInt32(cmd.Parameters["@Ret"].Value);
}
catch (Exception ex) { throw ex; }
finally { con.Close(); }
}
}
SQL代码:
PROCEDURE [dbo].[SaveInfo1]
(
-- ... parameters ...
)
AS
INSERT INTO Table1 ( ... ) Values ( ... )
RETURN SCOPE_IDENTITY
PROCEDURE [dbo].[SaveInfo2]
(
-- ... parameters ...
)
AS
DECLARE @SpecialID INT
INSERT INTO Table2 ( ... ) Values ( ... )
SET @SpecialID = SCOPE_IDENTITY()
INSERT INTO Table3 ( [ID], ... ) Values ( @SpecialID, ... )
RETURN SCOPE_IDENTITY()
答案 0 :(得分:2)
您的异常处理非常糟糕。 从不这样做:
catch (Exception ex) { throw ex; }
所有这一切都是在异常中搞砸堆栈跟踪。它使它看起来像是throw
。
从不这样做:
try{
mybusinessobject.savetodatabase()
} catch( Exception ex) {
Response.Redirect("Error.aspx");
}
你不知道发生了什么异常。您不知道重定向是否安全,最重要的是,您将丢失所有有关异常的信息!
您还应该养成实施using
块的习惯:
public static void savetodatabase()
{
using (SqlConnection con = new SqlConnection("Connectionstring"))
{
int ID1;
//store the billing contact
using (SqlCommand cmd1 = new SqlCommand("SaveInfo1", con))
{
cmd1.CommandType = CommandType.StoredProcedure;
//...
cmd1.Parameters.Add("@Ret", SqlDbType.Int);
cmd1.Parameters["@Ret"].Direction = ParameterDirection.ReturnValue;
con.Open();
cmd1.ExecuteNonQuery();
ID1 = Convert.ToInt32(cmd1.Parameters["@Ret"].Value);
}
if (ID1 <= 0)
{
return;
}
int ID2 = -1;
using (SqlCommand cmd = new SqlCommand("SaveInfo2", con))
{
cmd.CommandType = CommandType.StoredProcedure;
//...
con.Open();
cmd.ExecuteNonQuery();
ID2 = Convert.ToInt32(cmd.Parameters["@Ret"].Value);
}
}
}
using
块将确保资源将调用其Dispose
方法,无论是否抛出异常。
答案 1 :(得分:0)
是否有人刚刚从表中删除了某些记录?
答案 2 :(得分:0)
如果删除记录,即使稍后插入新记录,也不会回收其唯一标识符。如果您愿意,可以在SQL中使用RESEED将身份种子重置为0,但除非您擦除表,否则我建议不要这样做。否则,您最终可能会违反主键。
另外,请确保将列的标识种子设置为一次增加1。
答案 3 :(得分:0)
您的代码无关紧要,只需转到Web.config并使用适当的节点进行播放:
<customErrors mode="On|Off" />
P.S。
使用using
子句自动关闭连接,而不是finally
子句中的手动
答案 4 :(得分:0)
你可以测试捕获量。只需更改程序:
PROCEDURE [dbo].[SaveInfo1]
(
-- ... parameters ...
)
AS
INSERT INTO Table1 ( ... ) Values ( ..., some_out_of_range_value_here, ....)
RETURN SCOPE_IDENTITY()
有一些硬编码超出范围值(因此插入失败),然后运行你的应用程序......