Wywołanie procedury składowanej z wartością zwracaną

82

Próbuję wywołać procedurę składowaną z mojej aplikacji C # systemu Windows. Procedura składowana działa na lokalnym wystąpieniu programu SQL Server 2008. Mogę wywołać procedurę składowaną, ale nie mogę odzyskać wartości z procedury składowanej. Ta procedura składowana ma zwrócić następną liczbę w sekwencji. Zrobiłem badania online i wszystkie witryny, które widziałem, wskazywały, że to rozwiązanie działa.

Kod procedury składowanej:

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

Kod wywołujący procedurę składowaną:

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

Próbowałem również użyć DataSetdo pobrania wartości zwracanej z tym samym wynikiem. Czego mi brakuje, aby uzyskać wartość zwracaną z mojej procedury składowanej? Jeśli potrzebujesz więcej informacji, daj mi znać.

Wesley
źródło

Odpowiedzi:

165

Musisz dodać parametr powrotu do polecenia:

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
źródło
3
Czy musisz również dodać @ReturnValdo procedury składowanej?
muttley91
4
Nie, nie musisz dodawać do sp (instrukcja return wyzwala wypełnienie parametru oznaczonego wartością ReturnValue)
ufosnowcat
10
Tak przy okazji, nie ma znaczenia, jak nazwiesz parametr wartości zwracanej wartości.
Clay
wielkie dzięki, szukałem sposobu na prawidłowe uzyskanie wartości zwrotu, to naprawdę zadziałało. niesamowite!
Oswaldo Zapata
4
Wartość zwracana przez procedurę składowaną powinna być używana tylko do wskazania sukcesu (zero) lub niepowodzenia / ostrzeżenia (niezerowa), a nie zwracania danych. W tym celu użyj OUTPUTparametru lub zestawu wyników.
Dan Guzman,
5

Wiem, że to jest stare, ale natknąłem się na to z Google.

Jeśli masz wartość zwracaną w procedurze składowanej, powiedz „Return 1” - nie używając parametrów wyjściowych.

Możesz wykonać następujące czynności - „@RETURN_VALUE” jest dyskretnie dodawane do każdego obiektu polecenia. NIE MUSISZ WYRAŹNIE DODAĆ

    cmd.ExecuteNonQuery();
    rtn = (int)cmd.Parameters["@RETURN_VALUE"].Value;
Gary
źródło
2
Cześć Gary. Czy masz cytat?
Michael
5
Nie wierzę, że wystąpienie cmd będzie miało parametr nazwany w RETURN_VALUE w SqlParameterCollection, chyba że zostanie dodany jawnie. Dlatego jeśli rozważasz zastosowanie powyższego podejścia przez Gary'ego, upewnij się, że dodano cmd.Parameters.Add (new SqlParameter ("@ RETURN_VALUE", SqlDbType.Int)); cmd.Parameters ["@ RETURN_VALUE"]. Direction = ParameterDirection.ReturnValue; Uważam jednak, że NIE trzeba dodawać @RETURN_VALUE do definicji procedury składowanej. Może to miał na myśli Gary.
jbooker
4

Wersja EnterpriseLibrary na moim komputerze miała inne parametry. To działało:

        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
źródło
3

ExecuteScalar(); będzie działać, ale parametr wyjściowy byłby lepszym rozwiązaniem.

Justin Dearing
źródło
7
Funkcja ExecuteScalar () nie działa, chyba że „wybierzesz” zwracaną wartość.
Soori
2

Miałem podobny problem z wywołaniem SP zwracającym błąd, że oczekiwany parametr nie został uwzględniony. Mój kod był następujący.
Procedura składowana:

@Result int OUTPUT

I C#:

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

Podczas rozwiązywania problemów zdałem sobie sprawę, że procedura składowana RZECZYWISTE szukała kierunku „InputOutput”, więc następująca zmiana rozwiązała problem.

            r

Result.Direction = ParameterDirection.InputOutput;

Paweł
źródło
1
„Parametry wyjściowe” to nie to samo, co wartości zwracane procedury składowanej.
Dai
0

Lub jeśli używasz EnterpriseLibrary zamiast standardowego ADO.NET ...

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
źródło
0

To jest bardzo krótki przykład zwracania pojedynczej wartości z procedury:

SQL:

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

Kod C #:

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
źródło
-8

Widzę, że druga jest zamknięta. Więc w zasadzie tutaj jest przybliżony mój kod. Myślę, że brakuje ci komentarza cmd. Na przykład, jeśli moja procedura magazynu to call: DBO.Test. Musiałbym napisać cmd = "DBO.test". Następnie wpisz polecenie równe procedurze przechowywania i bla bla bla

Connection.open();
String cmd="DBO.test"; //the command
Sqlcommand mycommand;
Deszcz
źródło