asp.net/sql服务器试试看是怎么回事?

时间:2009-07-29 18:04:06

标签: asp.net sql exception exception-handling

我在我的代码中发现了一个错误,我对它最初是如何发生的事感到困惑。

我的问题是,我在数据库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()

5 个答案:

答案 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()

有一些硬编码超出范围值(因此插入失败),然后运行你的应用程序......