Chame um procedimento armazenado com o parâmetro em c #


138

Posso excluir, inserir e atualizar meu programa e tento fazer uma inserção chamando um procedimento armazenado criado do meu banco de dados.

Esta inserção de botão faz o trabalho bem.

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);
    } 

Este é o início do botão para chamar o procedimento nomeado sp_Add_contactpara adicionar um contato. Os dois parâmetros para sp_Add_contact(@FirstName,@LastName). Eu procurei no google por um bom exemplo, mas não achei nada interessante.

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
Apenas um pouco mais de informação - você não deve nomear os procedimentos armazenados do aplicativo com um prefixo sp_, como acima com sp_Add_contact. o prefixo sp_ é uma convenção de nomenclatura de processos armazenados no sistema que, quando o SQL vê, pesquisará todos os procedimentos armazenados no sistema antes de qualquer processo armazenado no aplicativo ou no espaço do usuário. Por uma questão de desempenho, se você se importa com isso em seu aplicativo, o prefixo sp_ diminuirá seus tempos de resposta.
Robert Achmann

Respostas:


265

É praticamente o mesmo que executar uma consulta. No seu código original, você está criando um objeto de comando, colocando-o na cmdvariável e nunca o utilizando. Aqui, no entanto, você usará isso em vez de da.InsertCommand.

Além disso, use a usingpara todos os objetos descartáveis, para ter certeza de que eles são descartados corretamente:

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
mas se esse procedimento retornar dados, como posso capturá-lo em c #?
MA9H 16/04

8
@ M009: Então você usa ExecuteReaderou ExecuteScalarpara chamá-lo.
Guffa

2
@ M009: Sim, essa é outra maneira de fazer a mesma coisa. O adaptador de dados usa ExecuteReader.
Guffa

1
@DylanChen: Isso depende das configurações do banco de dados. A configuração padrão é que os identificadores não diferenciam maiúsculas de minúsculas.
Guffa 10/10

1
@DylanChen: é a configuração de agrupamento do banco de dados que determina se os identificadores diferenciam maiúsculas de minúsculas.
Guffa

36

Você precisa adicionar parâmetros, pois é necessário que o SP execute

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 é uma má ideia; O SQL Server nem sempre usa o comprimento correto para nvarchar ou varchar, causando uma conversão implícita. É melhor especificar explicitamente o comprimento do parâmetro e adicionar o valor separadamente usando parameter.Value = txtfirstname.
George Stocker

14

cmd.Parameters.Add(String parameterName, Object value)está obsoleto agora. Em vez disso, usecmd.Parameters.AddWithValue(String parameterName, Object value)

Add (String parameterName, Object value) foi preterido. Use AddWithValue (String parameterName, Object value)

Não há diferença em termos de funcionalidade. A razão pela qual eles reprovaram o cmd.Parameters.Add(String parameterName, Object value)favor AddWithValue(String parameterName, Object value)é dar mais clareza. Aqui está a referência do MSDN para o mesmo

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
Você tem um link ou fonte para a reivindicação que cmd.Parameters.Addfoi descontinuada?
David

7
@ TonyG: isso não é verdade, a resposta aceita usa a sobrecarga preferencial da Addqual também não é preterida. AddWithValuetambém não é a melhor maneira, pois infere o tipo do parâmetro a partir do valor do parâmetro. Isso geralmente leva a planos de execução incorretos ou conversões incorretas. Também não valida o parâmetro em primeiro lugar (tipo fe se, Datetimemas você passa a String). Você pode ver aqui que apenas o argumento Addque leva Objectcomo segundo é preterido.
Tim Schmelter

2
AddWithValuetem apenas a mesma funcionalidade que Addcom Object, mas não é a maneira preferida. Ambos precisam inferir o tipo.
Tim Schmelter

2
Você está absolutamente certo, @ TimSchmelter. Minha leitura do texto foi falha. Obrigado pela correção. Estou escrevendo um novo código em que usarei Add (). E vou mudar meu voto positivo nesta resposta para um voto negativo, pois Rahul Nikate estava tão enganado quanto eu.
TonyG

2
@ TimSchmelter Obrigado pelo seu conselho. Eu editei minha resposta.
Rahul Nikate

3

Como alternativa, tenho uma biblioteca que facilita o trabalho com procs: 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

Os .NET Data Providers consistem em várias classes usadas para conectar-se a uma fonte de dados, executar comandos e retornar conjuntos de registros. O objeto de comando no ADO.NET fornece vários métodos Execute que podem ser usados ​​para executar as consultas SQL em uma variedade de modas.

Um procedimento armazenado é um objeto executável pré-compilado que contém uma ou mais instruções SQL. Em muitos casos, os procedimentos armazenados aceitam parâmetros de entrada e retornam vários valores. Os valores dos parâmetros podem ser fornecidos se um procedimento armazenado for gravado para aceitá-los. Um procedimento armazenado de amostra com aceitação do parâmetro de entrada é fornecido abaixo:

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

O procedimento armazenado acima está aceitando o nome de um país (@COUNTRY VARCHAR (20)) como parâmetro e retorna todos os editores do país de entrada. Depois que o CommandType estiver definido como StoredProcedure, você poderá usar a coleção Parameters para definir parâmetros.

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

O código acima passando o parâmetro country para o procedimento armazenado do aplicativo 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();
        }
    }
}

A sua resposta não usa usando blocos que é uma prática recomendada. Além disso, deve haver um bloco try catch para lidar com quaisquer exceções.
Trisped
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.