Rufen Sie eine gespeicherte Prozedur mit dem Parameter in c # auf

138

Ich kann in meinem Programm löschen, einfügen und aktualisieren und versuche, eine Einfügung durchzuführen, indem ich eine erstellte gespeicherte Prozedur aus meiner Datenbank aufrufe.

Dies ist eine Knopfleiste, die ich gut funktionieren lasse.

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

Dies ist der Anfang der Schaltfläche zum Aufrufen der Prozedur sp_Add_contactzum Hinzufügen eines Kontakts. Die beiden Parameter für sp_Add_contact(@FirstName,@LastName). Ich habe auf Google nach einem guten Beispiel gesucht, aber nichts Interessantes gefunden.

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
quelle
8
Nur eine zusätzliche Information - Sie sollten Ihre gespeicherten Prozeduren Ihrer Anwendung nicht mit einem Präfix sp_ benennen, wie oben mit sp_Add_contact. Das Präfix sp_ ist eine vom System gespeicherte Prozessbenennungskonvention, die, wenn SQL dies sieht, zuerst alle gespeicherten Systemprozeduren durchsucht, bevor Anwendungen oder Benutzerbereiche gespeicherte Prozesse ausführen. Aus Gründen der Leistung verschlechtert das Präfix sp_ Ihre Antwortzeiten, wenn Sie dies in Ihrer Anwendung berücksichtigen.
Robert Achmann

Antworten:

265

Es ist so ziemlich das gleiche wie das Ausführen einer Abfrage. In Ihrem ursprünglichen Code erstellen Sie ein Befehlsobjekt, fügen es in die cmdVariable ein und verwenden es niemals. Hier verwenden Sie dies jedoch anstelle von da.InsertCommand.

Verwenden Sie außerdem a usingfür alle Einwegobjekte, damit Sie sicher sind, dass sie ordnungsgemäß entsorgt werden:

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
quelle
7
Aber wenn diese Prozedur Daten zurückgibt, wie kann ich sie in C # abfangen?
MA9H
8
@ M009: Dann benutzt du ExecuteReaderoder ExecuteScalarum es aufzurufen.
Guffa
2
@ M009: Ja, das ist eine andere Möglichkeit, dasselbe zu tun. Der Datenadapter verwendet ExecuteReader.
Guffa
1
@ DylanChen: Das hängt von den Datenbankeinstellungen ab. Die Standardeinstellung ist, dass Bezeichner nicht zwischen Groß- und Kleinschreibung unterscheiden.
Guffa
1
@DylanChen: Es ist die Sortiereinstellung der Datenbank, die bestimmt, ob bei Bezeichnern zwischen Groß- und Kleinschreibung unterschieden wird.
Guffa
36

Sie müssen Parameter hinzufügen, da dies für die Ausführung des SP erforderlich ist

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
quelle
7
AddWithValue ist eine schlechte Idee; SQL Server verwendet nicht immer die richtige Länge für nvarchar oder varchar, was zu einer impliziten Konvertierung führt. Es ist besser, die Länge des Parameters explizit anzugeben und den Wert dann separat mit hinzuzufügen parameter.Value = txtfirstname.
George Stocker
14

cmd.Parameters.Add(String parameterName, Object value)ist jetzt veraltet. Verwenden Sie stattdessencmd.Parameters.AddWithValue(String parameterName, Object value)

Add (String parameterName, Object value) ist veraltet. Verwenden Sie AddWithValue (String parameterName, Object value)

Es gibt keinen Unterschied in der Funktionalität. Der Grund , warum sie die veraltet cmd.Parameters.Add(String parameterName, Object value)für AddWithValue(String parameterName, Object value)mehr Klarheit zu geben. Hier ist die MSDN-Referenz dafür

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
quelle
2
Haben Sie einen Link oder eine Quelle zu dem Anspruch, der cmd.Parameters.Addveraltet ist?
David
7
@TonyG: das stimmt nicht, die akzeptierte Antwort verwendet die bevorzugte Überlastung, von Addder auch nicht veraltet ist. AddWithValueDies ist auch nicht der beste Weg, da der Typ des Parameters vom Parameterwert abgeleitet wird. Dies führt häufig zu schlechten Ausführungsplänen oder falschen Konvertierungen. Es validiert den Parameter auch nicht in erster Linie (zB Typ, wenn DatetimeSie aber a übergeben String). Sie können hier sehen , dass nur Adddas , was Objectals zweites Argument verwendet wird, veraltet ist.
Tim Schmelter
2
AddWithValuehat genau die gleiche Funktionalität wie Addmit Object, aber es ist nicht der bevorzugte Weg. Beide müssen den Typ ableiten.
Tim Schmelter
2
Du hast absolut Recht, @TimSchmelter. Meine Lektüre des Textes war fehlerhaft. Danke für die Korrektur. Ich schreibe einen neuen Code, in dem ich Add () verwenden werde. Und ich werde meine Gegenstimme zu dieser Antwort in eine Gegenstimme ändern, da Rahul Nikate genauso falsch lag wie ich.
TonyG
2
@ TimSchmelter Vielen Dank für Ihren Rat. Ich habe meine Antwort bearbeitet.
Rahul Nikate
3

Als Alternative habe ich eine Bibliothek, die das Arbeiten mit Prozessen erleichtert: 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
quelle
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
quelle
0

Die .NET-Datenanbieter bestehen aus einer Reihe von Klassen, mit denen eine Verbindung zu einer Datenquelle hergestellt, Befehle ausgeführt und Datensätze zurückgegeben werden. Das Befehlsobjekt in ADO.NET bietet eine Reihe von Ausführungsmethoden, mit denen die SQL-Abfragen auf verschiedene Arten ausgeführt werden können.

Eine gespeicherte Prozedur ist ein vorkompiliertes ausführbares Objekt, das eine oder mehrere SQL-Anweisungen enthält. In vielen Fällen akzeptieren gespeicherte Prozeduren Eingabeparameter und geben mehrere Werte zurück. Parameterwerte können angegeben werden, wenn eine gespeicherte Prozedur geschrieben wurde, um sie zu akzeptieren. Eine gespeicherte Beispielprozedur mit akzeptierenden Eingabeparametern ist unten angegeben:

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

Die oben gespeicherte Prozedur akzeptiert einen Ländernamen (@COUNTRY VARCHAR (20)) als Parameter und gibt alle Herausgeber aus dem eingegebenen Land zurück. Sobald der CommandType auf StoredProcedure festgelegt ist, können Sie mithilfe der Parameters-Auflistung Parameter definieren.

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

Der obige Code, der den Länderparameter von der C # -Anwendung an die gespeicherte Prozedur übergibt.

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
quelle
Ihre Antwort verwendet nicht mit Blöcken , die eine bewährte Methode ist. Außerdem sollte es einen try catch-Block geben, um Ausnahmen zu behandeln.
Trisped