Asp.net 如何使用SQL Server存储过程?

Asp.net 如何使用SQL Server存储过程?,asp.net,sql-server,Asp.net,Sql Server,在过去一周左右的时间里,我一直在构建一个连接到SQLServer2008数据库的ASP站点。我从来没有使用过存储过程,我想知道是否有人能给我一些关于如何在ASP方法中创建和使用存储过程的指导。我正在努力使网站的代码尽可能简单和优雅。下面是我试图将其转换为存储过程的代码: private void ExecuteInsert(string name, string type) { SqlConnection conn = new SqlConnection(GetConnectio

在过去一周左右的时间里,我一直在构建一个连接到SQLServer2008数据库的ASP站点。我从来没有使用过存储过程,我想知道是否有人能给我一些关于如何在ASP方法中创建和使用存储过程的指导。我正在努力使网站的代码尽可能简单和优雅。下面是我试图将其转换为存储过程的代码:

    private void ExecuteInsert(string name, string type)
{
    SqlConnection conn = new SqlConnection(GetConnectionStringHM());
    string sql = "INSERT INTO tblSoftwareTitles (SoftwareName, SoftwareType) VALUES " 
        +"(@SoftwareName,@SoftwareSystemType)";

    try
    {
        conn.Open();
        SqlCommand cmd = new SqlCommand(sql, conn);
        SqlParameter[] param = new SqlParameter[2];
        //param[0] = new SqlParameter("@SoftwareID);
        param[0] = new SqlParameter("@SoftwareName", SqlDbType.NVarChar, 200);
        param[1] = new SqlParameter("@SoftwareType", SqlDbType.Int);

        param[0].Value = name;
        param[1].Value = type;

        for (int i= 0; i < param.Length; i++)
        {
            cmd.Parameters.Add(param[i]);
        }
        cmd.CommandType = CommandType.Text;
        cmd.ExecuteNonQuery();
    }
    catch (System.Data.SqlClient.SqlException ex)
    {
        string msg ="Insert Error:";
        msg += ex.Message;
        throw new Exception(msg);
    }

    finally
    {
        conn.Close();
    }

    }

这只是一个简单的插入,它从条目表单中获取两个参数并将它们插入数据库。任何帮助都将不胜感激,因为我觉得这将是一个有用的事情,知道以后的线。提前谢谢

你要找的答案就在这篇文章中

对于那篇文章中被接受的答案,我要改进的一点是,答案中的示例没有使用任何USING语句。最好将连接和命令放在USING语句中,这样它们就会被自动释放


另一种方法是使用Microsoft企业库与SQL Server DB交互。我认为这比使用普通的老式SqlConnection和SqlCommand更容易。

您要寻找的答案是在这篇文章中

对于那篇文章中被接受的答案,我要改进的一点是,答案中的示例没有使用任何USING语句。最好将连接和命令放在USING语句中,这样它们就会被自动释放


另一种方法是使用Microsoft企业库与SQL Server DB交互。我认为这比使用普通的老式SqlConnection和SqlCommand更容易。

您应该了解MSDN基础知识:

您不需要使用for循环使事情复杂化

try
  {
     sqlConnection = new SqlConnection(dbConnectionString);
     SqlCommand command = new SqlCommand(sql, sqlConnection);
     command.CommandType = CommandType.StoredProcedure;
     command.Parameters.Add("@SoftwareName", SqlDbType.NVarChar, 200).Value = SoftwareNameHere;
     command.Parameters.Add("@SoftwareType",  SqlDbType.Int).Value = SoftwareTypeHere;
     sqlConnection.Open();
     return command.ExecuteNonQuery();
  }
catch (SqlException ex)
  {
     Console.WriteLine("SQL Error" + ex.Message.ToString());
     return 0;
  }
finally
  {
     conn.Close(); 
  }
如果您使用的是.NET 3.5或更高版本,则可以使用负责资源处置的using代码块。我不完全确定,但据我记忆所及,这是在.NET3.5中引入的,以取代Try/Finally代码块,该代码块要求开发人员通过代码手动处理连接对象等资源

using (SqlConnection con = new SqlConnection { dbConnectionString })
{
    con.Open();
    try
    {   
        using (SqlCommand command = new SqlCommand { CommandType = CommandType.StoredProcedure, Connection = con, CommandTimeout = 300, CommandText = "sp_Test" })      
        {
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add("@SoftwareName", SqlDbType.NVarChar, 200).Value = SoftwareNameHere;
            command.Parameters.Add("@SoftwareType",  SqlDbType.Int).Value = SoftwareTypeHere;

            command.ExecuteNonQuery();
        }
    }
    catch(SqlException ex)
    {
        //ex.ToString message here;
    }
}

您应该查看MSDN基础知识:

您不需要使用for循环使事情复杂化

try
  {
     sqlConnection = new SqlConnection(dbConnectionString);
     SqlCommand command = new SqlCommand(sql, sqlConnection);
     command.CommandType = CommandType.StoredProcedure;
     command.Parameters.Add("@SoftwareName", SqlDbType.NVarChar, 200).Value = SoftwareNameHere;
     command.Parameters.Add("@SoftwareType",  SqlDbType.Int).Value = SoftwareTypeHere;
     sqlConnection.Open();
     return command.ExecuteNonQuery();
  }
catch (SqlException ex)
  {
     Console.WriteLine("SQL Error" + ex.Message.ToString());
     return 0;
  }
finally
  {
     conn.Close(); 
  }
如果您使用的是.NET 3.5或更高版本,则可以使用负责资源处置的using代码块。我不完全确定,但据我记忆所及,这是在.NET3.5中引入的,以取代Try/Finally代码块,该代码块要求开发人员通过代码手动处理连接对象等资源

using (SqlConnection con = new SqlConnection { dbConnectionString })
{
    con.Open();
    try
    {   
        using (SqlCommand command = new SqlCommand { CommandType = CommandType.StoredProcedure, Connection = con, CommandTimeout = 300, CommandText = "sp_Test" })      
        {
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add("@SoftwareName", SqlDbType.NVarChar, 200).Value = SoftwareNameHere;
            command.Parameters.Add("@SoftwareType",  SqlDbType.Int).Value = SoftwareTypeHere;

            command.ExecuteNonQuery();
        }
    }
    catch(SqlException ex)
    {
        //ex.ToString message here;
    }
}

由于您的代码已经使用了参数,您已经完成了90%的工作。你所要做的就是:

将insert语句放入存储过程中,保持与动态语句相同的参数定义。 将CommandType.Text更改为CommandType.StoredProcess 将命令文本更改为存储过程的名称。
由于您的代码已经使用了参数,您已经完成了90%的工作。你所要做的就是:

将insert语句放入存储过程中,保持与动态语句相同的参数定义。 将CommandType.Text更改为CommandType.StoredProcess 将命令文本更改为存储过程的名称。
在阅读了一些关于这个主题的文章后,我发现了一些有用的文章,它们确实质疑我对存储过程的需求

这篇文章给出了一个很好的观点,说明了存储过程在编码、调试和错误报告方面是多么的麻烦而不是帮助,并且非常笨拙和乏味

上面这篇链接的文章对参数化查询做了很好的解释,解释了为什么它们对于降低sql注入的风险是必要的,并提出了这样一个观点:这些参数化查询以与过程类似的方式进行缓存,从而使它们获得了可比的性能增益

我觉得在我的情况下,将参数化sql查询编码到我的ASP页面将是最明智的做法,因为这些页面将存储在服务器上并由客户端访问。我想,如果这是一个安装在多台客户机上的应用程序,那么对SQL进行硬编码将不是一个理想的选择,因此存储过程将是我了解的最佳方式

如果有兴趣,可以在这里找到存储过程与参数化sql的后续内容,以及指向参数每一方的不同链接


希望这个小小的答案能帮助其他考虑使用存储过程而不是参数化SQL的人,反之亦然

在阅读了一些关于这个主题的文章后,我发现了一些有用的文章,它们确实质疑我对存储过程的需求

这篇文章给出了一个很好的观点,说明了存储过程在编码、调试和错误报告方面是多么的麻烦而不是帮助,并且非常笨拙和乏味

这篇与上面一篇相关的文章对参数化做了很好的解释,解释了为什么它们 这对于降低sql注入的风险是必要的,并且还提出了这样一个观点,即这些参数化查询以与过程类似的方式进行缓存,从而使它们获得了相当的性能收益

我觉得在我的情况下,将参数化sql查询编码到我的ASP页面将是最明智的做法,因为这些页面将存储在服务器上并由客户端访问。我想,如果这是一个安装在多台客户机上的应用程序,那么对SQL进行硬编码将不是一个理想的选择,因此存储过程将是我了解的最佳方式

如果有兴趣,可以在这里找到存储过程与参数化sql的后续内容,以及指向参数每一方的不同链接



希望这个小答案能帮助其他考虑使用存储过程而不是参数化SQL的人,反之亦然

好答案,但我会改进它,将您的SqlConnection和SqlCommand放在使用块的内部,以便它们被自动处理。我不知道提问者使用的是.NET的哪个版本,这就是我使用旧方法的原因。这看起来确实更整洁!我也可以在代码的其他部分使用它,所以非常感谢!我也在使用.net 4Close。连接应该发生在finally块中。否则,您可能会得到僵尸连接,这将阻塞您的SQL Server。关于.NET版本,这一点很好。不过,为了让OP受益,他应该知道,最好将像SqlConnection这样的一次性对象放在USING块中。回答得好,但我会改进它,将您的SqlConnection和SqlCommand放在使用块的内部,以便它们被自动处理。我不知道提问者使用的是.NET的哪个版本,这就是我使用旧方法的原因。这看起来确实更整洁!我也可以在代码的其他部分使用它,所以非常感谢!我也在使用.net 4Close。连接应该发生在finally块中。否则,您可能会得到僵尸连接,这将阻塞您的SQL Server。关于.NET版本,这一点很好。不过,为了让OP受益,他应该知道,最好将像SqlConnection这样的一次性对象放在USING块中。因此,使用USING时,不需要connection.close语句?这是正确的。如果您使用的是USING块,那么连接应该自动释放。因此,使用USING时,不需要connection.close语句?这是正确的。如果您使用的是USING块,连接应该会自动处理。谢谢,我现在就试试。谢谢,我现在就试试。我个人不喜欢使用太多的存储过程,尤其是对于简单的查询。但是,为了提高可重用性,最好至少将查询与代码的其余部分隔离开来。例如,我有一些项目,其中我将查询存储在一个XML文件中,并有一个实用程序类按名称检索查询。这样就可以重用相同的查询。你也可以将它们作为常量字符串存储在某个地方。这很有意义。实际上,我只是想进入一个良好的实践,保持Sql参数化,并尽可能地将其分开。在我看来,这是一种更安全、更易于管理的编码方法。我仍然在用我的代码进行迭代过程,尽可能地改进它。因为我不打算使用存储过程,所以您所描述的将是下一个逻辑步骤。我个人不喜欢使用太多的存储过程,尤其是对于简单的查询。但是,为了提高可重用性,最好至少将查询与代码的其余部分隔离开来。例如,我有一些项目,其中我将查询存储在一个XML文件中,并有一个实用程序类按名称检索查询。这样就可以重用相同的查询。你也可以将它们作为常量字符串存储在某个地方。这很有意义。实际上,我只是想进入一个良好的实践,保持Sql参数化,并尽可能地将其分开。在我看来,这是一种更安全、更易于管理的编码方法。我仍然在用我的代码进行迭代过程,尽可能地改进它。因为我不打算使用存储过程,所以您所描述的将是下一个逻辑步骤。