在C#中使用参数调用存储过程


138

我可以在程序中执行删除,插入和更新操作,并尝试通过从数据库中调用创建的存储过程来进行插入操作。

这个按钮插入我做得很好。

private void btnAdd_Click(object sender, EventArgs e)
{
        SqlConnection con = new SqlConnection(dc.Con);
        SqlCommand cmd = new SqlCommand("Command String", con);

        da.InsertCommand = new SqlCommand("INSERT INTO tblContacts VALUES (@FirstName, @LastName)", con);
        da.InsertCommand.Parameters.Add("@FirstName", SqlDbType.VarChar).Value = txtFirstName.Text;
        da.InsertCommand.Parameters.Add("@LastName", SqlDbType.VarChar).Value = txtLastName.Text;

        con.Open();
        da.InsertCommand.ExecuteNonQuery();
        con.Close();

        dt.Clear();
        da.Fill(dt);
    } 

这是按钮的开始,该按钮将调用名为sp_Add_contact添加联系人的过程。的两个参数sp_Add_contact(@FirstName,@LastName)。我在Google上搜索了一个很好的例子,但没有发现任何有趣的事情。

private void button1_Click(object sender, EventArgs e)
{
        SqlConnection con = new SqlConnection(dc.Con);
        SqlCommand cmd = new SqlCommand("Command String", con);
        cmd.CommandType = CommandType.StoredProcedure;

        ???

        con.Open();
        da. ???.ExecuteNonQuery();
        con.Close();

        dt.Clear();
        da.Fill(dt);
    }

8
只是一点点信息-您不应该使用sp_前缀来命名应用程序存储过程,就像上面的sp_Add_contact一样。sp_前缀是系统存储过程的命名约定,当SQL看到它时,它将在所有应用程序或用户空间存储的proc之前首先搜索所有系统存储过程。作为性能问题,如果您在应用程序中关心它,则sp_前缀将缩短响应时间。
罗伯特·阿赫曼

Answers:


265

它与运行查询几乎相同。在原始代码中,您正在创建一个命令对象,将其放入cmd变量中,并且永远不要使用它。但是,在这里,您将使用而不是da.InsertCommand

另外,using对所有一次性物品都使用A ,以确保正确放置它们:

private void button1_Click(object sender, EventArgs e) {
  using (SqlConnection con = new SqlConnection(dc.Con)) {
    using (SqlCommand cmd = new SqlCommand("sp_Add_contact", con)) {
      cmd.CommandType = CommandType.StoredProcedure;

      cmd.Parameters.Add("@FirstName", SqlDbType.VarChar).Value = txtFirstName.Text;
      cmd.Parameters.Add("@LastName", SqlDbType.VarChar).Value = txtLastName.Text;

      con.Open();
      cmd.ExecuteNonQuery();
    }
  }
}

7
但是,如果此过程返回数据,如何在C#中捕获它?
MA9H 2013年

8
@ M009:然后您使用ExecuteReader或对其ExecuteScalar进行调用。
Guffa

2
@ M009:是的,这是做同一件事的另一种方法。数据适配器使用ExecuteReader
Guffa

1
@DylanChen:这取决于数据库设置。默认设置是标识符不区分大小写。
加法

1
@DylanChen:数据库的排序规则设置确定标识符是否区分大小写。
加法

36

您必须添加参数,因为执行SP需要此参数

using (SqlConnection con = new SqlConnection(dc.Con))
{
    using (SqlCommand cmd = new SqlCommand("SP_ADD", con))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@FirstName", txtfirstname.Text);
        cmd.Parameters.AddWithValue("@LastName", txtlastname.Text);
        con.Open();
        cmd.ExecuteNonQuery();
    }            
}

7
AddWithValue是一个坏主意;SQL Server并不总是对nvarchar或varchar使用正确的长度,从而导致隐式转换的发生。最好明确指定参数的长度,然后使用分别添加值parameter.Value = txtfirstname
乔治·斯托克2014年

14

cmd.Parameters.Add(String parameterName, Object value)现在已弃用。改为使用cmd.Parameters.AddWithValue(String parameterName, Object value)

Add(String parameterName,Object value)已被弃用。使用AddWithValue(String parameterName,Object value)

功能上没有区别。他们弃用的原因cmd.Parameters.Add(String parameterName, Object value)赞成的AddWithValue(String parameterName, Object value)是给更清晰。这是相同的MSDN参考

private void button1_Click(object sender, EventArgs e) {
  using (SqlConnection con = new SqlConnection(dc.Con)) {
    using (SqlCommand cmd = new SqlCommand("sp_Add_contact", con)) {
      cmd.CommandType = CommandType.StoredProcedure;

      cmd.Parameters.AddWithValue("@FirstName", SqlDbType.VarChar).Value = txtFirstName.Text;
      cmd.Parameters.AddWithValue("@LastName", SqlDbType.VarChar).Value = txtLastName.Text;

      con.Open();
      cmd.ExecuteNonQuery();
    }
  }
}

2
您是否有cmd.Parameters.Add不赞成的声明的链接或来源?
戴维(David)

7
@TonyG:这是不正确的,接受的答案使用首选的重载Add也不弃用。 AddWithValue也不是最好的方法,因为它可以从参数值中推断出参数的类型。这通常会导致执行计划不正确或转换错误。它也不会首先验证参数(如果Datetime您传递,则为fe类型String)。您可以在此处看到不赞成仅AddObjectas作为第二个参数。
蒂姆·施密特

2
AddWithValue具有Add与with 相同的功能Object,但这不是首选方式。两者都需要推断类型。
蒂姆·施密特2015年

2
@TimSchmelter,您绝对正确。我对文本的阅读存在缺陷。感谢您的更正。我正在编写一些将要使用Add()的新代码。我会根据这个答案将我的赞成票改为反对票,因为Rahul Nikate和我一样被误解了。
TonyG

2
@TimSchmelter谢谢您的建议。我已经编辑了答案。
拉胡尔·尼卡特

3

作为替代,我有一个可以轻松使用proc的库:https : //www.nuget.org/packages/SprocMapper/

SqlServerAccess sqlAccess = new SqlServerAccess("your connection string");
    sqlAccess.Procedure()
         .AddSqlParameter("@FirstName", SqlDbType.VarChar, txtFirstName.Text)
         .AddSqlParameter("@FirstName", SqlDbType.VarChar, txtLastName.Text)
         .ExecuteNonQuery("StoredProcedureName");

0
public void myfunction(){
        try
        {
            sqlcon.Open();
            SqlCommand cmd = new SqlCommand("sp_laba", sqlcon);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.ExecuteNonQuery();
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {
            sqlcon.Close();
        }
}

0

.NET数据提供程序由许多用于连接数据源,执行命令和返回记录集的类组成。ADO.NET中的Command Object提供了许多Execute方法,可用于以各种方式执行SQL查询。

存储过程是一个包含一个或多个SQL语句的预编译可执行对象。在许多情况下,存储过程接受输入参数并返回多个值。如果编写存储过程来接受参数值,则可以提供它们。下面给出了一个接受输入参数的示例存储过程:

  CREATE PROCEDURE SPCOUNTRY
  @COUNTRY VARCHAR(20)
  AS
  SELECT PUB_NAME FROM publishers WHERE COUNTRY = @COUNTRY
  GO

上面的存储过程接受国家名称(@COUNTRY VARCHAR(20))作为参数,并返回输入国家/地区的所有发布者。一旦将CommandType设置为StoredProcedure,就可以使用Parameters集合来定义参数。

  command.CommandType = CommandType.StoredProcedure;
  param = new SqlParameter("@COUNTRY", "Germany");
  param.Direction = ParameterDirection.Input;
  param.DbType = DbType.String;
  command.Parameters.Add(param);

上面的代码将国家/地区参数从C#应用程序传递到存储过程。

using System;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string connetionString = null;
            SqlConnection connection ;
            SqlDataAdapter adapter ;
            SqlCommand command = new SqlCommand();
            SqlParameter param ;
            DataSet ds = new DataSet();

            int i = 0;

            connetionString = "Data Source=servername;Initial Catalog=PUBS;User ID=sa;Password=yourpassword";
            connection = new SqlConnection(connetionString);

            connection.Open();
            command.Connection = connection;
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = "SPCOUNTRY";

            param = new SqlParameter("@COUNTRY", "Germany");
            param.Direction = ParameterDirection.Input;
            param.DbType = DbType.String;
            command.Parameters.Add(param);

            adapter = new SqlDataAdapter(command);
            adapter.Fill(ds);

            for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
            {
                MessageBox.Show (ds.Tables[0].Rows[i][0].ToString ());
            }

            connection.Close();
        }
    }
}

您的答案不使用使用块,这是最佳实践。另外,应该有一个try catch块来处理任何异常。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.