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);       
}
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. Commented Feb 20, 2015 at 10:53
  • SELECT SCOPE_IDENTITY() Commented Feb 20, 2015 at 10:53
  • 1
    What is objData and what does .ModifyData() on that object do?? Commented Feb 20, 2015 at 11:00
  • Steve - yeah that was my idea, but i'm not hardcore to sql yet :) Commented Feb 20, 2015 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(); } Commented Feb 20, 2015 at 11:04

7 Answers 7

11

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...

Sign up to request clarification or add additional context in comments.

2 Comments

Okay, i will try this, and how do i access the return value on my asp codebehinde?
@HenrikS: the new ID value is returned from the CreateAlbum method as an int ....
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);

5 Comments

i'm getting an error: ExecuteNonQuery: Connection property has not been initialized
Obviously you need to set the connection property of objCmd and make sure it is open before Executing it: objCmd.Connection = YouConnection;
Now i just get the value 0
Are you sure tblFotoalbum table has an identity column?
I like this answer because it works with parameters
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)

4 Comments

Isnt this just for triggers?
Perhaps you mean for the OP to use the OUTPUT clause?
any chance you've copied this from: stackoverflow.com/a/5228819/57475. If so, link to that answer and say where you've taken/adapted the code from. regardless of that fact, this still doesn't really answer the question in any direct manner.
The OUTPUT clauses requires an INTO with a temporary (in memory) table! You should complete your otherwise valid example.
1

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

4 Comments

This is rather a comment than an answer.
I spent 2 hours to learn this answer. maybe you understood wrongly me according to my bad english.
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.
yes thanks. this was my first comment this platform.
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.

4 Comments

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.
We don't know what ModifyData does, but probably this is the best way to have a duplicate record in the db.
@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
Yes Steve, the OP should provide for us what the ModifyData does.
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.

Comments

0

check with SCOPE_IDENTITY()..

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.