Aufrufen der gespeicherten Prozedur mit Rückgabewert

80

Ich versuche, eine gespeicherte Prozedur aus meiner C # -Fensteranwendung aufzurufen. Die gespeicherte Prozedur wird auf einer lokalen Instanz von SQL Server 2008 ausgeführt. Ich kann die gespeicherte Prozedur aufrufen, aber den Wert nicht von der gespeicherten Prozedur zurückrufen. Diese gespeicherte Prozedur soll die nächste Nummer in der Sequenz zurückgeben. Ich habe online recherchiert und alle Websites, die ich gesehen habe, haben darauf hingewiesen, dass diese Lösung funktioniert.

Gespeicherter Prozedurcode:

ALTER procedure [dbo].[usp_GetNewSeqVal]
      @SeqName nvarchar(255)
as
begin
      declare @NewSeqVal int
      set NOCOUNT ON
      update AllSequences
      set @NewSeqVal = CurrVal = CurrVal+Incr
      where SeqName = @SeqName

      if @@rowcount = 0 begin
print 'Sequence does not exist'
            return
      end

      return @NewSeqVal
end

Code, der die gespeicherte Prozedur aufruft:

SqlConnection conn = new SqlConnection(getConnectionString());
conn.Open();

SqlCommand cmd = new SqlCommand(parameterStatement.getQuery(), conn);
cmd.CommandType = CommandType.StoredProcedure;

SqlParameter param = new SqlParameter();

param = cmd.Parameters.Add("@SeqName", SqlDbType.NVarChar);
param.Direction = ParameterDirection.Input;
param.Value = "SeqName";

SqlDataReader reader = cmd.ExecuteReader();

Ich habe auch versucht, mit a DataSetden Rückgabewert mit dem gleichen Ergebnis abzurufen. Was fehlt mir, um den Rückgabewert von meiner gespeicherten Prozedur zu erhalten? Wenn Sie weitere Informationen benötigen, lassen Sie es mich bitte wissen.

Wesley
quelle

Antworten:

161

Sie müssen dem Befehl einen Rückgabeparameter hinzufügen:

using (SqlConnection conn = new SqlConnection(getConnectionString()))
using (SqlCommand cmd = conn.CreateCommand())
{
    cmd.CommandText = parameterStatement.getQuery();
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("SeqName", "SeqNameValue");

    var returnParameter = cmd.Parameters.Add("@ReturnVal", SqlDbType.Int);
    returnParameter.Direction = ParameterDirection.ReturnValue;

    conn.Open();
    cmd.ExecuteNonQuery();
    var result = returnParameter.Value;
}
Alex Aza
quelle
3
Müssen Sie auch @ReturnValdie gespeicherte Prozedur ergänzen ?
Muttley91
4
Nein, Sie müssen nicht zum sp hinzufügen (die return-Anweisung löst das Füllen des mit ReturnValue gekennzeichneten Parameters aus)
ufosnowcat
10
Es spielt keine Rolle, wie Sie den Parameter return val nennen.
Clay
Vielen Dank, ich habe nach einer Möglichkeit gesucht, den Rückgabewert richtig zu ermitteln. Das hat wirklich bei mir funktioniert. genial!
Oswaldo Zapata
4
Der Rückgabewert der gespeicherten Prozedur sollte nur verwendet werden, um Erfolg (Null) oder Fehler / Warnung (Nicht-Null) anzuzeigen, nicht um Daten zurückzugeben. Verwenden Sie dazu einen OUTPUTParameter oder eine Ergebnismenge.
Dan Guzman
5

Ich weiß, dass dies alt ist, aber ich bin mit Google darauf gestoßen.

Wenn Ihre gespeicherte Prozedur einen Rückgabewert enthält, sagen Sie "Rückgabe 1" - ohne Ausgabeparameter.

Sie können Folgendes tun: "@RETURN_VALUE" wird stillschweigend zu jedem Befehlsobjekt hinzugefügt. KEINE NOTWENDIGE HINZUFÜGEN

    cmd.ExecuteNonQuery();
    rtn = (int)cmd.Parameters["@RETURN_VALUE"].Value;
Gary
quelle
2
Hallo Gary. Hast du zufällig ein Zitat?
Michael
5
Ich glaube nicht, dass die cmd-Instanz einen Parameter in RETURN_VALUE in der SqlParameterCollection haben wird, es sei denn, er wird explizit hinzugefügt. Wenn Sie den obigen Ansatz von Gary in Betracht ziehen, stellen Sie daher sicher, dass Sie cmd.Parameters.Add (neuer SqlParameter ("@ RETURN_VALUE", SqlDbType.Int)) hinzugefügt haben. cmd.Parameters ["@ RETURN_VALUE"]. Direction = ParameterDirection.ReturnValue; Ich glaube jedoch, dass Sie der Definition der gespeicherten Prozedur NICHT @RETURN_VALUE hinzufügen müssen. Vielleicht hat Gary das so gemeint.
jbooker
4

ExecuteScalar () funktioniert, aber ein Ausgabeparameter wäre eine überlegene Lösung.

Justin Dearing
quelle
5
ExecuteScalar () funktioniert nur, wenn Sie den Rückgabewert "auswählen".
Soori
4

Die Version von EnterpriseLibrary auf meinem Computer hatte andere Parameter. Das hat funktioniert:

        SqlParameter retval = new SqlParameter("@ReturnValue", System.Data.SqlDbType.Int);
        retval.Direction = System.Data.ParameterDirection.ReturnValue;
        cmd.Parameters.Add(retval);
        db.ExecuteNonQuery(cmd);
        object o = cmd.Parameters["@ReturnValue"].Value;
RaSor
quelle
2

Ich hatte ein ähnliches Problem mit dem SP-Aufruf, der einen Fehler zurückgab, dass ein erwarteter Parameter nicht enthalten war. Mein Code war wie folgt.
Gespeicherte Prozedur:

@Result int OUTPUT

Und C#:

            SqlParameter result = cmd.Parameters.Add(new SqlParameter("@Result", DbType.Int32));
            result.Direction = ParameterDirection.ReturnValue;

Bei der Fehlerbehebung wurde mir klar, dass die gespeicherte Prozedur tatsächlich nach einer Richtung für "InputOutput" suchte, sodass die folgende Änderung das Problem behebt.

            r

Result.Direction = ParameterDirection.InputOutput;

Paul
quelle
"Ausgabeparameter" sind übrigens nicht dasselbe wie Rückgabewerte für gespeicherte Prozeduren.
Dai
0

Oder wenn Sie EnterpriseLibrary anstelle von Standard-ADO.NET verwenden ...

Database db = DatabaseFactory.CreateDatabase();
using (DbCommand cmd = db.GetStoredProcCommand("usp_GetNewSeqVal"))
{
    db.AddInParameter(cmd, "SeqName", DbType.String, "SeqNameValue");
    db.AddParameter(cmd, "RetVal", DbType.Int32, ParameterDirection.ReturnValue, null, DataRowVersion.Default, null);

    db.ExecuteNonQuery(cmd);

    var result = (int)cmd.Parameters["RetVal"].Value;
}
Dunc
quelle
0

Dies ist ein sehr kurzes Beispiel für die Rückgabe eines einzelnen Werts aus einer Prozedur:

SQL:

CREATE PROCEDURE [dbo].[MakeDouble] @InpVal int AS BEGIN 
SELECT @InpVal * 2; RETURN 0; 
END

C # -Code:

int inpVal = 11;
string retVal = "?";
using (var sqlCon = new SqlConnection(
    "Data Source = . ; Initial Catalog = SampleDb; Integrated Security = True;"))
{
    sqlCon.Open();
    retVal = new SqlCommand("Exec dbo.MakeDouble " + inpVal + ";", 
        sqlCon).ExecuteScalar().ToString();
    sqlCon.Close();
}
Debug.Print(inpVal + " * 2 = " + retVal); 
//> 11 * 2 = 22
Michael Borg
quelle
-8

Ich sehe, der andere ist geschlossen. Im Grunde ist hier das Grobe meines Codes. Ich denke, Sie vermissen den String cmd Kommentar. Zum Beispiel, wenn meine Speicherprozedur aufgerufen wird: DBO.Test. Ich müsste cmd = "DBO.test" schreiben. Führen Sie dann den Befehlstyp aus, der der Speicherprozedur entspricht, und bla bla bla

Connection.open();
String cmd="DBO.test"; //the command
Sqlcommand mycommand;
Regen
quelle
tolle Antwort,
klatsch klatsch klatsch