2016-07-13 25 views
1

Ich habe diese Stored Procedure geschrieben:Warum gibt SCOPE_IDENTITY() -1 zurück?

ALTER PROCEDURE [cairs].[sp_SaveR] 
    -- Add the parameters for the stored procedure here 
@fname nvarchar(50), 
@lname nvarchar(50), 
@mname nchar(10), 
@sigDate date   
AS 
BEGIN 
    SET NOCOUNT ON; 
    insert into tUser 
(fname, 
lname, 
mname, 
sigDate 
) 
values 
(
@fname, 
@lname, 
@mname, 
@sigDate) 

select SCOPE_IDENTITY() 

END 

Dies ist der C# -Code ich um eine Verbindung herzustellen verwenden:

try 
{ 
    using (SqlConnection conn = new SqlConnection(cCon.getConn())) 
    { 
     using (SqlCommand cmd = conn.CreateCommand()) 
     { 
      conn.Open(); 

      cmd.CommandText = "sp_SaveR";           
      cmd.CommandType = CommandType.StoredProcedure; 

      cmd.Parameters.Add(new SqlParameter("@fname", fName)); 
      cmd.Parameters.Add(new SqlParameter("@lname", lName)); 
      cmd.Parameters.Add(new SqlParameter("@mname", mName));      
      cmd.Parameters.Add(new SqlParameter("@sigDate", sigDate)); 

      int userID = (int)cmd.ExecuteNonQuery(); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    throw(ex); 
} 

Mein userID ist immer -1 Rückkehr, obwohl die Datensätze erfolgreich eingefügt werden in die DB-Tabelle. Warum passiert das?

+7

'ExecuteNonQuery' scheint, wie die falsche Methode, die hier verwendet werden - sicherlich wollen, sind Sie die Ergebnisse der letzten Abfrage verbrauchen, so' ExecuteReader' (oder wahrscheinlicher , 'ExecuteScalar') erscheint angemessen. Auch nicht relevant für Ihr aktuelles Problem, aber Sie sollten das Präfix 'sp_' vermeiden - es ist von Microsoft für seine Systemprozeduren reserviert. –

+2

Das ist, weil Sie den Rückgabewert von Ihrer Prozedur erhalten. Sie sollten eine OUTPUT-Variable verwenden. Als Randnotiz sollten Sie in Erwägung ziehen, das Präfix sp_ nicht zu verwenden (oder besser gar kein Präfix). http://sqlperformance.com/2012/10/t-sql-queries/sp_prefix –

+0

danke euch beiden! Ich hatte keine Ahnung von der SP, ich dachte, es wäre die Norm für gespeicherte Verfahren benennen: -/ –

Antwort

3

ExecuteNonQuery verwirft die Ergebnismenge. Die Zahl, die es zurückgibt, ist normalerweise die Anzahl der betroffenen Zeilen, aber darauf kann man sich nicht wirklich verlassen. In Ihrem Fall gibt es -1 zurück, weil Sie eine gespeicherte Prozedur ausführen, es würde 1 zurückgeben, wenn Sie die SQL inlineed.

Sie möchten stattdessen ExecuteScalar verwenden, die die erste Spalte aus der ersten Zeile in der ersten Ergebnismenge liest.

+0

Eine andere Option wäre, ein hinzufügen Ausgabeparameter zum proc. –

0

Dies funktioniert wie vorgesehen. Der Rückgabewert ist die Anzahl der geänderten Zeilen. Wenn Sie einen gespeicherten Prozess aufrufen oder Daten auswählen, lautet der Wert -1.

Von MSDN ...

SqlCommand.ExecuteNonQuery

Für UPDATE, INSERT und DELETE-Anweisungen ist der Rückgabewert die Anzahl der Zeilen, die von dem Befehl betroffen. Wenn ein Trigger für eine Tabelle vorhanden ist, die eingefügt oder aktualisiert wird, enthält der Rückgabewert die Nummer der Zeilen, die von der Einfüge- oder Aktualisierungsoperation betroffen sind, und die Nummer der Zeilen, die vom Trigger oder Trigger betroffen sind. Für alle anderen Typen von Anweisungen ist der Rückgabewert -1. Wenn ein Rollback auftritt, ist der Rückgabewert ebenfalls -1.

0

Sie sollten den Parameter output verwenden, um die ID wie unten zu erhalten.

ALTER PROCEDURE [cairs].[sp_SaveR] 
-- Add the parameters for the stored procedure here 
@fname nvarchar(50), 
@lname nvarchar(50), 
@mname nchar(10), 
@sigDate date, 
@NewId int OUTPUT   
AS 
BEGIN 
SET NOCOUNT ON; 
insert into tUser 
(fname, 
lname, 
mname, 
sigDate 
) 
values 
(
@fname, 
@lname, 
@mname, 
@sigDate) 

select @NewId = SCOPE_IDENTITY() 

END 

In C#:

try 
{ 
    using (SqlConnection conn = new SqlConnection(cCon.getConn())) 
    { 
     using (SqlCommand cmd = conn.CreateCommand()) 
     { 
      conn.Open(); 

      cmd.CommandText = "sp_SaveR";           
      cmd.CommandType = CommandType.StoredProcedure; 

      cmd.Parameters.Add(new SqlParameter("@fname", fName)); 
      cmd.Parameters.Add(new SqlParameter("@lname", lName)); 
      cmd.Parameters.Add(new SqlParameter("@mname", mName));      
      cmd.Parameters.Add(new SqlParameter("@sigDate", sigDate)); 
      cmd.Parameters.Add("@NewId", SqlDbType.Int).Direction = ParameterDirection.Output; 

      cmd.ExecuteNonQuery(); 
      int userId = Convert.ToInt32(cmd.Parameters["@NewId"].Value); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    throw(ex); 
} 
Verwandte Themen