I'm trying to get the last inserted id out of the database. I've tried many different code snippets but still having no luck. Here's the code I'm using for the inserts. I need the last insert id from the first to insert as nId in the second. I've tried SELECT ##IDENTITY but null value errors appeared which I couldn't locate. Can anybody show me the correct code please?
// Insert new user
daUsers.Insert(textBoxUsername.Text, textBoxPassword.Text);
// Insert new Twitter OAuth
daTwitterOAuth.Insert(nId, textBoxConsumerKey.Text, textBoxConsumerSecret.Text, textBoxToken.Text, textBoxTokenSecret.Text);
If you're trying to add a new record, you should be calling TableAdapter.Insert, not TableAdapter.Update
You can't create a second command to the database and use ##IDENTITY to get back the ID that was previously generated... this has to be returned within the same session, otherwise SQL would have no idea which ID you are expecting to receive.
If you set the execute mode of the table adapter to scalar, then the ID will be the return value of the method call. Please see this Question and Answer on the same issue that you're experiencing.
Someone has mentioned ##Identity which is fine, but what if somebody else performs an insert elsewhere before you reach that line in SQL?
I'd do this.
Create Procedure [Proc]
#Id as int output = 0
as
Insert into Table
Select * from AnotherTable
SET #Id = (SELECT Scope_Identity)
Then in .NET add your output parameter.
Been there already! In the code above I'm using an insert method, changed the execute mode to scalar and this is my sql:
INSERT INTO [dbTblUsers]([strUsername], [strPassword])
VALUES (#p1,#p2);
SELECT ##IDENTITY;
How do I cast ##identity into an int? Like this?
nId = (int)daUsers.InsertQuery(textBoxUsername.Text, textBoxPassword.Text);
Related
Code-first auto generates an insert procedure code as below for a table that has ProductID as primary key (identity column).
CREATE PROCEDURE [dbo].[InsertProducts]
#ProductName [nvarchar](max),
#Date [datetime],
AS
BEGIN
INSERT dbo.ProductsTable([ProductName], [Date])
VALUES (#ProductName, #Date)
-- identity stuff starts here
DECLARE #ProductID int
SELECT #ProductID = [ProductID]
FROM dbo.FIT_StorageLocations
WHERE ##ROWCOUNT > 0 AND [ProductID] = scope_identity()
SELECT t0.[ProductID]
FROM dbo.ProductsTable AS t0
WHERE ##ROWCOUNT > 0 AND t0.[ProductID] = #ProductID
END
GO
Could you please explain the code that handles the identity column? Also, if an insert procedure is to be manually written from scratch, would it be handled differently?
If for example I would remove this auto generated code, I would encounter one of the following errors:
Procedure ....expects parameter '#ProductID', which was not supplied
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.
In the app, this is how I call the procedure which works fine until I try to mess with the code first auto generated SQL:
using (var db = new AppContext())
{
var record = new ProductObj()
{
ProductName= this.ProductName,
Date = DateTime.UtcNow
};
db.ProductDbSet.Add(record);
db.SaveChanges();
}
I guess there are two things to be explained here.
Why a SELECT statement when I insert stuff?
Let's first see what a regular insert by Entity Framework looks like. By "regular" I mean an insert without mapping CUD actions to stored procedures. The normal pattern is:
INSERT [dbo].[Product]([Name], ...)
VALUES (#0, ...)
SELECT [Id]
FROM [dbo].[Product]
WHERE ##ROWCOUNT > 0 AND [Id] = scope_identity()
So the INSERT is followed by a SELECT. This is because EF needs to know the identity value that the database assigns to the new Product to assign it to the entity object's Product.ProductId property and to track the entity. If for some reason you'd decide to do an update immediately after the insert, EF will be able to generate an update statement like UPDATE ... WHERE Id = #0.
When the insert is handled by a stored procedure, the sproc should return the new Id value in a way that looks like the regular insert. It expects to receive a one-column result set of which the column is named after the identity column. It should contain one row, the new identity value.
So that's why there is a SELECT statement in there, and why EF complains if you remove it. But, you might ask, does EF really need 7 lines of code to get an assigned identity value?
Why so much code?
Honestly, I have to speculate a bit here, because it isn't documented as far as I can find. But let's look at a minimal working version:
INSERT [dbo].[Products]([Name])
VALUES (#Name)
SELECT scope_identity() AS ProductId;
This does the job. It's even the standard example of many tutorials, including official ones, on mapping CUD actions to stored procedures.
But a database can be stuffed with triggers, constraints, defaults, etc. It's hard to predict their influence on the returned scope_identity() under the wide range of circumstances EF may encounter. So EF wants to guarantee that the returned value really belongs to the newly inserted record. And that a record has actually been inserted in the first place. That's why it adds the SELECT from the Product table, including the ##ROWCOUNT.
To implement these safeguards, a minimal version would be:
INSERT [dbo].[Products]([Name])
VALUES (#Name)
SELECT t0.[ProductId]
FROM [dbo].[Products] AS t0
WHERE ##ROWCOUNT > 0 AND t0.[ProductId] = scope_identity()
Same as in the regular insert.
That's as far as I can follow EF. It puzzles me a bit that this single SELECT apparently is enough for a regular INSERT but not for a stored procedure. I can't explain why there are two SELECTs in the generated code.
How can I get get generated ID from primary key and then add it to another table in ASP.NET via SCOPE_IDENTITY?
For example:
Last generated ID on column NRRENDOR is number 26, I have deleted the rows. Now when I add datas to the database the nexy generated ID on NRRENDOR will be number 27. That number I want it to add to column NRD.
In your INSERT code, assuming it's in a stored procedure, using SCOPE_IDENTITY will get you the last identity that was inserted, which you can either reuse in the stored procedure or return to your app to use in another statement.
Some dummy SQL to demonstrate:
INSERT INTO NRRENDOR(SomeColumn) VALUES(1)
DECLARE #LastID int
// set #LastID to the last id inserted
SELECT #LastID = SCOPE_IDENTITY()
// to use in same procedure
INSERT INTO NRD (SomeColumn) VALUES(#LastID)
// to return it to code - or you could use an output parameter
SELECT #LastID
What has this got to do with ASP.NET? SQL would suffice.
INSERT INTO [Table2]( NRD)
SELECT MAX(NRRENDOR)
FROM Table1
' WITH (ROWLOCK, XLOCK, HOLDLOCK)
The correct way to do it will be to use #SCOPE_IDENTITY after you perform insertion as Tanner suggested. It will be worth noting that there is another way to get the current identity, ie, IDENT_CURRENT. You can use it like this
SELECT IDENT_CURRENT('Table1') + 1 as Current_Identity
Please note this too
Be cautious about using IDENT_CURRENT to predict the next generated
identity value. The actual generated value may be different from
IDENT_CURRENT plus IDENT_INCR because of insertions performed by other
sessions.
This comment from marc_s sums it all. How to get the next identity value from SQL Server
I will import many data rows from a csv file into a SQL Server database (through a web application). I need the auto generated id value back for the client.
If I do this in a loop, the performance is very bad (but I can use SCOPE_IDENTITY() without any problems).
A more performant solution would be a way like this:
INSERT INTO [MyTable]
VALUES ('1'), ('2'), ('3')
SELECT SCOPE_IDENTITY()
Is there any way to get all generated IDs and not only the last generated id?
No, SCOPE_IDENTITY() only gives you the one, latest inserted IDENTITY value. But you could check out the OUTPUT clause of SQL Server ....
DECLARE #IdentityTable TABLE (SomeKeyValue INT, NewIdentity INT)
INSERT INTO [MyTable]
OUTPUT Inserted.Keyvalue, Inserted.ID INTO #IdentityTable(SomeKeyValue, NewIdentity)
VALUES ('1'), ('2'), ('3')
Once you've run your INSERT statement, the table variable will hold "some key value" (for you, to identify the row) and the newly inserted ID values for each row inserted. Now go crazy with this! :-)
I am trying to return identity of last inserted row from a stored procedure.
A simplified version of my code looks like this:
CREATE PROCEDURE [sp_name]
#AuthorisationCode uniqueidentifier
AS
INSERT INTO [tablename]
([AuthorisationCode]
)
VALUES
(#AuthorisationCode
)
RETURN ##IDENTITY
GO
I am calling this stored procedure via Execute Scalar in Enterprise library 4.1.
It returns null. Anybody see what I am doing wrong.
I'd say you should be using SCOPE_IDENTITY() as ##identity will return the identity of the last thing inserted (which may not be your stored procedure if multiple queries are running simultaneously).
You also need to SELECT it, not RETURN it.
ExecuteScalar will return the first column value from the first row of a result set.
So...
SELECT SCOPE_IDENTITY();
is probably more what you want.
You should use select rather than return, but you should also use SCOPE_IDENTITY to prevent issues with the wrong identity being returned, ##IDENTITY is not limited to a specific scope.
SELECT SCOPE_IDENTITY()
More information can be found here:
http://msdn.microsoft.com/en-us/library/ms190315.aspx
you should use select ##identity
BGREX.BGREXDataTable _bRexDataTable = new BGREX.BGREXDataTable();
BGREX.BGREXRow bgRexRow = _bRexDataTable.NewBGREXRow();
bgRexRow.BGRes_TITLE = "abc";
bgRexRow.BGRes_VERSION = 123;
_bRexDataTable.AddBGREXRow(bgRexRow);
int rewEffected = Adapter.Update(_bRexDataTable);
Have beed using above to insert record in Database, workes perfect. Now I need the id (Primary key) of newly inserted record which is auto generated, instead of rows affected to be returned from
Adapter.Update(_bRexDataTable);
It looks like I need SCOPE_IDENTITY() function, but I am not sure where to include this in designer as designers is not happy with following syntax added to the actual insert query.
It woks fine in sqlserver Management console though
DECLARE #ROWI_D int
INSERT INTO TABLE
.....
.....
.....
VALUES
("val1","val2",.......................)
SET ROW_ID = SCOPE_IDENTITY()
i'm not sure of a way to do this using sql statements with the commands. i'm not saying that it can't be done, i just never work with the statements, always through sprocs.
through the use of stored procedures you can define an output parameter which you can set equal to SCOPE_IDENTITY() in the sproc and then ensure that you pass that parameter into the command while settings it's direction as output.
sorry i don't have a solution for the direct sql call, but maybe someone else with more experience working in this way will chime in.
here's a link to a thread which discusses this same topic and a possible answer. but there's no verification whether the suggested solution worked or not.
Best way to do this is to change to a stored procedure that returns the value you want in a parameter. Post the code for doing the update you have now and I (or someone else) will show you how to refactor it to use a stored procedure. It is not hard.