Appeler une procédure stockée avec un paramètre en c #

138

Je peux faire une suppression, une insertion et une mise à jour dans mon programme et j'essaye de faire une insertion par appel d'une procédure stockée créée à partir de ma base de données.

C'est un insert de bouton que je fais bien fonctionner.

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

C'est le début du bouton pour appeler la procédure nommée sp_Add_contactpour ajouter un contact. Les deux paramètres pour sp_Add_contact(@FirstName,@LastName). J'ai cherché sur google un bon exemple mais je n'ai rien trouvé d'intéressant.

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);
    }
FrankSharp
la source
8
Juste un peu d'information supplémentaire - vous ne devriez pas nommer vos procédures stockées d'application avec un préfixe sp_, comme ci-dessus avec sp_Add_contact. le préfixe sp_ est une convention de dénomination des procs stockés dans le système, qui, lorsque SQL le voit, effectuera une recherche dans toutes les procédures stockées du système avant tout processus stocké dans une application ou un espace utilisateur. En termes de performances, si vous vous souciez de cela dans votre application, le préfixe sp_ dégradera vos temps de réponse.
Robert Achmann

Réponses:

265

C'est à peu près la même chose que d'exécuter une requête. Dans votre code d'origine, vous créez un objet de commande, vous le placez dans la cmdvariable et ne l'utilisez jamais. Ici, cependant, vous utiliserez cela à la place de da.InsertCommand.

Utilisez également un usingpour tous les objets jetables, afin d'être sûr qu'ils sont correctement éliminés:

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();
    }
  }
}
Guffa
la source
7
mais si cette procédure renvoie des données, comment puis-je les attraper en C #?
MA9H
8
@ M009: Ensuite, vous utilisez ExecuteReaderou ExecuteScalarpour l'appeler.
Guffa
2
@ M009: Oui, c'est une autre façon de faire la même chose. L'adaptateur de données utilise ExecuteReader.
Guffa
1
@DylanChen: Cela dépend des paramètres de la base de données. Le paramètre par défaut est que les identificateurs ne sont pas sensibles à la casse.
Guffa
1
@DylanChen: c'est le paramètre de classement de la base de données qui détermine si les identificateurs sont sensibles à la casse.
Guffa
36

Vous devez ajouter des paramètres car ils sont nécessaires pour que le SP s'exécute

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();
    }            
}
Ravi Gadag
la source
7
AddWithValue est une mauvaise idée; SQL Server n'utilise pas toujours la longueur correcte pour nvarchar ou varchar, ce qui entraîne une conversion implicite. Il est préférable de spécifier la longueur du paramètre explicitement, puis d'ajouter la valeur séparément à l'aide de parameter.Value = txtfirstname.
George Stocker
14

cmd.Parameters.Add(String parameterName, Object value)est désormais obsolète. Utilisez plutôtcmd.Parameters.AddWithValue(String parameterName, Object value)

Add (String parameterName, Object value) est obsolète. Utiliser AddWithValue (String parameterName, Object value)

Il n'y a aucune différence en termes de fonctionnalité. La raison pour laquelle ils ont désapprouvé le cmd.Parameters.Add(String parameterName, Object value)en faveur de AddWithValue(String parameterName, Object value)est de donner plus de clarté. Voici la référence MSDN pour le même

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();
    }
  }
}
Rahul Nikate
la source
2
Avez-vous un lien ou une source vers la revendication qui cmd.Parameters.Addest obsolète?
David
7
@TonyG: ce n'est pas vrai, la réponse acceptée utilise la surcharge préférée Addqui n'est pas non plus obsolète. AddWithValuen'est pas non plus le meilleur moyen car il déduit le type du paramètre de la valeur du paramètre. Cela conduit souvent à de mauvais plans d'exécution ou à des conversions incorrectes. Il ne valide pas non plus le paramètre en premier lieu (type fe si Datetimemais vous passez a String). Vous pouvez voir ici que seul Addce qui prend un Objectdeuxième argument est obsolète.
Tim Schmelter
2
AddWithValuea juste les mêmes fonctionnalités Addqu'avec Object, mais ce n'est pas la méthode préférée. Les deux doivent déduire le type.
Tim Schmelter
2
Vous avez absolument raison, @TimSchmelter. Ma lecture du texte était erronée. Merci pour la correction. J'écris un nouveau code dans lequel j'utiliserai Add (). Et je changerai mon vote pour cette réponse en un vote négatif, car Rahul Nikate était aussi erroné que moi.
TonyG
2
@TimSchmelter Merci pour vos conseils. J'ai modifié ma réponse.
Rahul Nikate
3

Comme alternative, j'ai une bibliothèque qui facilite le travail avec 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");
Greg R Taylor
la source
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();
        }
}
user6916720
la source
0

Les fournisseurs de données .NET se composent d'un certain nombre de classes utilisées pour se connecter à une source de données, exécuter des commandes et renvoyer des jeux d'enregistrements. L'objet de commande dans ADO.NET fournit un certain nombre de méthodes Execute qui peuvent être utilisées pour effectuer les requêtes SQL de différentes manières.

Une procédure stockée est un objet exécutable précompilé qui contient une ou plusieurs instructions SQL. Dans de nombreux cas, les procédures stockées acceptent les paramètres d'entrée et renvoient plusieurs valeurs. Les valeurs de paramètre peuvent être fournies si une procédure stockée est écrite pour les accepter. Un exemple de procédure stockée avec acceptation du paramètre d'entrée est donné ci-dessous:

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

La procédure stockée ci-dessus accepte un nom de pays (@COUNTRY VARCHAR (20)) comme paramètre et renvoie tous les éditeurs du pays d'entrée. Une fois que CommandType est défini sur StoredProcedure, vous pouvez utiliser la collection Parameters pour définir des paramètres.

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

Le code ci-dessus transmet le paramètre de pays à la procédure stockée à partir de l'application 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();
        }
    }
}
Sudhakar Rao
la source
Votre réponse n'utilise pas en utilisant des blocs qui est une meilleure pratique. En outre, il devrait y avoir un bloc try catch pour traiter toutes les exceptions.
Trisped