7

I know this question has been on this site many times, but I can't get my code working.

I have an Insert statement, and I need the id from that statement on my asp.net page.

I'm getting the return value 0.

public int newid { get; set; }

public void CreateAlbum(string _titel, string _name, string _thumb, int _userid)
{
    objCMD = new SqlCommand(@"INSERT INTO tblFotoalbum 
                                  (fldAlbumHead, fldAlbumName, fldAlbumThumb, fldUserID_FK)
                              VALUES 
                                  (@titel, @name, @thumb, @userid);

                              SET @newid = SCOPE_IDENTITY()");

    objCMD.Parameters.AddWithValue("@titel", _titel);
    objCMD.Parameters.AddWithValue("@name", _name);
    objCMD.Parameters.AddWithValue("@thumb", _thumb);
    objCMD.Parameters.AddWithValue("@userid", _userid);
    objCMD.Parameters.AddWithValue("@newid", newid);

    objData.ModifyData(objCMD);       
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Henrik S
  • 105
  • 1
  • 1
  • 6
  • Did you expect the property newid to be set with the value of SCOPE_IDENTITY? This is not the way in which parameters work. – Steve Feb 20 '15 at 10:53
  • `SELECT SCOPE_IDENTITY()` – leppie Feb 20 '15 at 10:53
  • 1
    What is `objData` and what does `.ModifyData()` on that object do?? – marc_s Feb 20 '15 at 11:00
  • Steve - yeah that was my idea, but i'm not hardcore to sql yet :) – Henrik S Feb 20 '15 at 11:02
  • marc_s - objData is a instance of my DataAccess file, modifyData is: public void ModifyData(SqlCommand CMD) { CMD.Connection = strCon; strCon.Open(); CMD.ExecuteNonQuery(); strCon.Close(); } – Henrik S Feb 20 '15 at 11:04
  • possible duplicate of [How to get last inserted id?](http://stackoverflow.com/questions/5228780/how-to-get-last-inserted-id) – Tanner Feb 20 '15 at 11:10

7 Answers7

10

Try this:

public int CreateAlbum(string _titel, string _name, string _thumb, int _userid)
{
    // define return value - newly inserted ID
    int returnValue = -1;

    // define query to be executed
    string query = @"INSERT INTO tblFotoalbum (fldAlbumHead, fldAlbumName, fldAlbumThumb, fldUserID_FK)
                              VALUES (@titel, @name, @thumb, @userid);
                     SELECT SCOPE_IDENTITY();"

    // set up SqlCommand in a using block   
    using (objCMD = new SqlCommand(query, connection)) 
    {
        // add parameters using regular ".Add()" method 
        objCMD.Parameters.Add("@titel", SqlDbType.VarChar, 50).Value = _titel;
        objCMD.Parameters.Add("@name", SqlDbType.VarChar, 100).Value = _name;
        objCMD.Parameters.Add("@thumb", SqlDbType.VarChar, 100).Value = _thumb;
        objCMD.Parameters.Add("@userid", SqlDbType.VarChar, 25).Value = _userid;

        // open connection, execute query, close connection
        connection.Open();
        object returnObj = objCMD.ExecuteScalar();

        if(returnObj != null)
        {
           int.TryParse(returnObj.ToString(), out returnValue);
        }

        connection.Close();
    }

    // return newly inserted ID
    return returnValue;
}

Not sure how you can integrate that with your objData class - maybe you need to add a new method to that DAL class for this.

Check out Can we stop using AddWithValue() already? and stop using .AddWithValue() - it can lead to unexpected and surprising results...

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
3

Given the sql statement you are using, you need to configure @newid as an output parameter:

var newIdParam = objCMD.Parameters.Add("@newid", SqlDbType.Int32)
newIdParam.Direction = ParameterDirection.OutPut;

then you execute the command using ExecuteNonQuery, and after that you can read the ouptut parameter:

objCmd.ExecuteNonQuery();
int newId = Convert.ToInt32(newIdParam.Value);

EDIT: I guess ModifyData method set the connection property and calls ExecuteNonQuery, so your code would be:

objData.ModifyData(objCMD);      
int newId = Convert.ToInt32(newIdParam.Value);
Jesús López
  • 8,338
  • 7
  • 40
  • 66
1

It might be the case as this works for SQL SERVER 2000

  • for 2005+ use

    OUTPUT INSERTED.ID

Like

INSERT INTO Roles(UserId)
OUTPUT INSERTED.ID
VALUES(@UserId)
Tushar Gupta
  • 15,504
  • 1
  • 29
  • 47
1

if you are using CommandText you shouldn't forget adding "SELECT SCOPE_IDENTITY()" end of CommandText line.

Hakan Lekesiz
  • 111
  • 1
  • 5
  • This is rather a comment than an answer. – Yan Sklyarenko Mar 26 '20 at 08:42
  • I spent 2 hours to learn this answer. maybe you understood wrongly me according to my bad english. – Hakan Lekesiz Mar 26 '20 at 13:22
  • I apologize for the misunderstanding. My point was solely about the shape of the information, not the content. When you answer the question, you might want to give a more detailed explanation so that a person asking the question and others can benefit. In this particular case, I would expect to see some more details about why one should not forget adding `SELECT SCOPE_IDENTITY()`. Hope you get my point. – Yan Sklyarenko Mar 26 '20 at 14:59
  • yes thanks. this was my first comment this platform. – Hakan Lekesiz Mar 28 '20 at 22:03
0

You don't need an output variable to do it. You could just use a SELECT SCOPE_IDENTITY() to get the last id inserted on database and use the ExecuteScalar() method from DbCommand.

public int newid { get; set; }

public void CreateAlbum(string _titel, string _name, string _thumb, int _userid)
{
    objCMD = new SqlCommand(@"INSERT INTO tblFotoalbum 
                           (fldAlbumHead, fldAlbumName, fldAlbumThumb, fldUserID_FK)
                           VALUES 
                           (@titel, @name, @thumb, @userid);

                           SELECT SCOPE_IDENTITY()");

    objCMD.Parameters.AddWithValue("@titel", _titel);
    objCMD.Parameters.AddWithValue("@name", _name);
    objCMD.Parameters.AddWithValue("@thumb", _thumb);
    objCMD.Parameters.AddWithValue("@userid", _userid);
    objCMD.Parameters.AddWithValue("@newid", newid);

    objData.ModifyData(objCMD);     


    newid = (int)objCMD.ExecuteScalar();
}

I don't know objData object does, but take a look how you execute your command.

Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
  • 2
    Did you mean `SELECT` instead of SET? Anyway, using the `OUTPUT inserted.ID` clause is preferable. You use only a single insert statement and don't have to worry about inserting in multiple tables with identity keys in the same batch. – Panagiotis Kanavos Feb 20 '15 at 10:54
  • We don't know what ModifyData does, but probably this is the best way to have a duplicate record in the db. – Steve Feb 20 '15 at 10:54
  • 2
    @FelipeOriani this cannot end well. The ExecuteScalar runs everything not only the SELECT SCOPE_IDENTITY. If ModifyData inserts a record, calling again ExecuteScalar inserts another copy of the same data – Steve Feb 20 '15 at 10:59
  • Yes Steve, the OP should provide for us what the `ModifyData` does. – Felipe Oriani Feb 20 '15 at 11:03
0

The preferred solution (and AFAIK also the only really safe one) is to use the OUTPUT clause as in this example:

DECLARE @newIdTable(newid INT);
INSERT INTO table(...) OUTPUT INSERTED.ID INTO @newIdTable VALUES (...);
SELECT TOP 1 newid FROM @newIdTable;

I suggest you put this into a stored procedure and call it using ExecuteScalar, which would return the value of the last select.

Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139
0

check with SCOPE_IDENTITY()..

https://msdn.microsoft.com/en-IN/library/ms190315.asp

Viral Sarvaiya
  • 781
  • 2
  • 9
  • 29