Select Cast (Scope_identity) and executescalar - c#

Why doesn't this work? I get an error saying the number cannot be infinity. However, I had to take this away from an insert statement so that it doesn't post entries twice.
Where do I have to incorporate this piece of code to get it to allow my code to loop as a new ID?
cmd = new SqlCommand(#"SELECT CAST(scope_identity() as int)", con);
int aID = Convert.ToInt32(cmd.ExecuteScalar());

In general you can have a stored procedure to do the INSERT and return the last inserted identity with an out parameter, as you can see in an example here: http://www.objectreference.net/post/SCOPE_IDENTITY()-return-the-id-from-the-database-on-insert.aspx
CREATE PROCEDURE [dbo].[Customer_Insert]
#Name VARCHAR(255),
#Email VARCHAR(255),
#Phone VARCHAR(255),
#CustomerID INT OUTPUT
AS
BEGIN
INSERT INTO dbo.Customer ([Name], Email, Phone)
VALUES (#Name,#Email,#Phone)
SET #CustomerID = CAST(SCOPE_IDENTITY() AS INT)
END

Related

Select Scope Identity from Sql

I am executing an Insert query. I want to return the identity element. I am also using this same stored procedure. Inside another stored procedure to return the identity element.
Alter Proc Proc1
#name varchar(10),
#value int
As
Begin
insert into Table1
values (#name, #value)
return SCOPE_IDENTITY()
C# code:
I have a method to call my database every time, so I use that
_database.StoredProcedure = "Proc1";
_database.parameter("name","michael");
_database.parameter("value",10);
int id = Convert.ToInt32(_database.ExecuteScalar());
Here, I get id=0 every time //BUG
SQL other stored procedure:
Alter Proc2
// Some other logic
Execute #id = Proc1 #name, #value // THIS WORKS
Now, If I change Proc1's last line to Select SCOPE_IDENTITY() from RETURN SCOPE_IDENTITY() then C# code works but Proc2 returns 0.
What should I do such that it works in C# code and in Proc2 also.
I thought about an output parameter, but I don't know how would I call it with my this database method in C#.
If you want data out of a procedure the correct thing is to use output parameters. Do NOT use the return_value from your procedures. This value indicates a status of the execution, not data from the procedure.
Here is an example of what this might look like.
Alter Proc Proc1
#name varchar(10),
#value int,
#IdentityValue int OUTPUT
As
Begin
insert into Table1 values (#name,#value)
Select #IdentityValue = SCOPE_IDENTITY()
END
select * from table1
GO
Alter Proc2
(
#name varchar(10)
, #value int
, #IdentityValue int OUTPUT
)
as
//SOme other logic
declare #IdentityValue int
Execute Proc1 #name, #value, #IdentityValue OUTPUT
GO
Also, please notice that you have an insert in Proc1 but you don't specify the columns. This is very bad practice. If your table structure changes your procedure is broken. You should ALWAYS specify the columns in your insert.
Change your procedure body to like below, to change the RETURN statement to SELECT SCOPE_IDENTITY()
Alter Proc Proc1
#name varchar(10),
#value int
As
Begin
insert into Table1 values (#name,#value);
SELECT SCOPE_IDENTITY();
END
In that case, make it a output parameter and set that output parameter to scope_identity
Alter Proc Proc1
#name varchar(10),
#value int,
#ID INT OUTPUT
As
Begin
insert into Table1 values (#name,#value);
SET #ID = SCOPE_IDENTITY();
END
You can call the procedure
cmd.Parameters.Add("#ID", SqlDbType.Int, 0, "ID");
cmd.Parameters["#ID"].Direction = ParameterDirection.Output;
conn.Open();
cmd.ExecuteNonQuery();
int id = (int)cmd.Parameters["#ID"].Value;

output parameter returns null value when I run on ADO. NET in C#

I'm sure this question has already been answered in this forum. I went through most of them and tried all the possible fixes but it did not work in my case. I'm not sure where I'm going wrong.
My stored procedure works fine in SQL Server Management Studio. It is returning the output whenever I run my stored procedure. But the output parameter returns NULL value when I call it from my ADO. NET code. I'm pretty new to this. Any help to resolve this issue is very much appreciated.
Stored Procedure :
CREATE PROCEDURE [dbo].[sp_ZebraGetEmpName]
#EmpId int,
#EmpName varchar(40) out
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT EmployeeName
FROM ZebraPrinter.dbo.EmployeeInfo
WHERE EmpID = #EmpId
RETURN (#EmpName)
END
GO
ADO .NET Code :
public string GetEmpName(int EmpId)
{
string connStr = ConfigurationManager.ConnectionStrings["ZebraPrinterConnectionString"].ConnectionString;
SqlConnection con = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand("sp_ZebraGetEmpName", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#EmpId",EmpId);
cmd.Parameters.Add("#EmpName", SqlDbType.VarChar, 40);
cmd.Parameters["#EmpName"].Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteScalar();
con.Close();
string EmpName = cmd.Parameters["#EmpName"].Value.ToString();
return (EmpName);
}
You didn't assign any values to #EmpName variable in procedure so it will be NULL. Change the select query to assign value to #EmpName
Also you don't need procedure to do this.
SELECT #EmpName=EmployeeName
FROM ZebraPrinter.dbo.EmployeeInfo
WHERE EmpID = #EmpId
You getting the null value in the output parameter because you are not assigning the value to the output parameter.
When you are using a output parameter then you have to set it's value in the stored procedure to use it's value later.
Use:
SET #EmpName = (SELECT TOP 1 EmployeeName
FROM ZebraPrinter.dbo.EmployeeInfo
WHERE EmpID = #EmpId)
and your stored procedure should be like this:
CREATE PROCEDURE [dbo].[sp_ZebraGetEmpName]
#EmpId int,
#EmpName varchar(40) out
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET #EmpName = (SELECT TOP 1 EmployeeName
FROM ZebraPrinter.dbo.EmployeeInfo
WHERE EmpID = #EmpId)
END
GO
Returning something, setting an output parameter value, and selecting something are three different things.
You can set #EmpName like NoDisplayName's answer and leave your C# code as-is, or you can just run the select and pull the value when you execute the query:
CREATE PROCEDURE [dbo].[sp_ZebraGetEmpName]
#EmpId int
AS
BEGIN
SELECT EmployeeName
FROM ZebraPrinter.dbo.EmployeeInfo
WHERE EmpID = #EmpId
END
string empName = (string)cmd.ExecuteScalar();
What you're seeing in Management Studio when you run this is not the return value, but rather the query result. The return value of your query would be null.

get the id of the last inserted row in

I saw few solutions here but none worked. I tried SCOPE_IDENTITY() didn't wotk. the id is autoincrement.
This is my stored procedure
CREATE PROCEDURE [dbo].[uploadVid]
#video varbinary(MAx),
#vidTitle varchar(50),
#vidCategory varchar(50),
#vidDate date,
#vidDescription varchar(Max),
#vidName varchar(50),
#vidSize bigint
AS
INSERT INTO Video(video, vidTitle, vidCategory, vidDate, vidDescription, vidName, vidSize)
VALUES (#video, #vidTitle, #vidCategory, #vidDate, #vidDescription, #vidName, #vidSize)
& in the back end I tried
Object i = register.ExecuteScalar();
&
int newId = (Int32)register.ExecuteScalar();
I put a break point and it gave me a value of null or 0. any help appreciated
Thanks
try this
CREATE PROCEDURE [dbo].[uploadVid]
#video varbinary(MAx),
#vidTitle varchar(50),
#vidCategory varchar(50),
#vidDate date,
#vidDescription varchar(Max),
#vidName varchar(50),
#vidSize bigint
AS
begin
declare #id as int --assuming your identity column is int
INSERT INTO Video(video, vidTitle, vidCategory, vidDate, vidDescription, vidName, vidSize)
VALUES (#video, #vidTitle, #vidCategory, #vidDate, #vidDescription, #vidName, #vidSize)
set #id = scope_identity()
select #id --return the value for executescaler to catch it
end
Probably you don't execute the commands in the correct sequence: (supposing you are using an SQL Server DB)
SqlCommand cmd = new SqlCommand("uploadVid", connnection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(.....)
......
// After adding the parameters you execute the command to insert the new row....
int rowsInserted = cmd.ExecuteNonQuery();
if(rowsInserted > 0)
{
SqlCommand cmd1 = new SqlCommand("SELECT SCOPE_IDENTITY()", connection);
int newID = (int)cmd1.ExecuteScalar();
}
ExecuteScalar returns only the value of the first row in the first column of the query executed. In case of an insert this value is meaningless. You need an ExecuteNonQuery that returns the rows inserted by the command. After that run a new command with the SELECT SCOPE_IDENTITY() command text with the ExecuteScalar. This, of course, if you cannot modify the SP, the answer from th1rdey3 is better if you could change the proc because it avoids a run-trip to the database.

Inserting AutoIncrementID into DB

Hi i'm having trouble with inserting incremented userid inside my db below is my table,stored proc,and my code.
CREATE TABLE [dbo].[Assignment2]
(
userID int PRIMARY KEY IDENTITY(1,1),
Name varchar(255) NOT NULL,
Age int NOT NULL,
Hobbies varchar(255)
)
and a stored procedure
ALTER PROCEDURE [db].[p_Assignment2_ins]
#userID int,
#Name nvarchar(100),
#Age int,
#Hobbies nvarchar(100)
AS
INSERT INTO [DB].[db].[Assignment2]
([Name]
,[Age]
,[Hobbies])
VALUES
(#Name
,#Age
,#Hobbies)
If ##Error <> 0
Return -1
Select #userID = ##Identity // this one just get the latest id that we inserted right?
Return 0
I have some question :
I want to know how do we insert the UserID from the code behind because If the table is empty at first shouldn't we insert a data first into the table
How do we generate an AutoIncrementID from codebehind and insert it
SqlConnection conn = new SqlConnection(ts.ConnMethod());
SqlCommand cmd = new SqlCommand("p_Assignment2_ins", conn);
cmd.CommandType = CommandType.StoredProcedure;
//I'm missing how we should add the IncrementedID
cmd.Parameters.AddWithValue("#Name", TextBox1.Text);
cmd.Parameters.AddWithValue("#Age", TextBox2.Text);
cmd.Parameters.AddWithValue("#Hobbies", TextBox3.Text);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
Any help is really appreciated thanks
Select #userID = ##Identity // this one just get the latest id that we inserted right?
No, you should use SCOPE_IDENTITY(). ##Identity returns the last id, yes, but not the last id from your insert. If you have a trigger, for example, that also produces an insert on a another table as a result of your insert, you will get the id inserted on the other table by that trigger.
Here's a nice article explaining the differences.
As far as inserting autoincrement values on your table; you can't do this unless you disable the constraint first but in essence, this shouldn't be necessary unless you are doing some sort of data import. In your scenario, you should be able to just insert values on the other columns except the identity field with autoincrement. The database will take care of inserting the appropriate value for you.
If you have AUTOINCREMENT field, you SHOULD NOT insert and generate values at all. DB is doing all by itself. So, remove the code that inserts ID-s

Getting autonumber primary key from MS SQL Server

I am currently working in C#, and I need to insert a new record into one table, get the new primary key value, and then use that as a foreign key reference in inserting several more records. The Database is MS SQL Server 2003. All help is appreciated!
The way to get the identity of the inserted row is with the SCOPE_IDENTITY() function. If you're using stored procedures then this would look something like the following to return the row identity as an output parameter.
CREATE PROCEDURE dbo.MyProcedure
(
#RowId INT = NULL OUTPUT
)
AS
INSERT INTO MyTable
(
Column1
,Column2
,...
)
VALUES
(
#Param1
,#Param2
,...
);
SET #RowId = SCOPE_IDENTITY();
You can then use this value for any subsequent inserts (alternatively, if you can pass the data all into the stored procedure, then you can use it in the remainder of the procedure body).
If you're passing the SQL in dynamically then you use much the same technique, but with a single string with statement delimiters (also ; in SQL), e.g.:
var sql = "INSERT INTO MyTable (Column1, Column2, ...) VALUES (#P1, #P2, ...);" +
"SELECT SCOPE_IDENTITY();";
Then if you execute this using ExecuteScalar you'll be able to get the identity back as the scalar result and cast it to the right type. Alternatively you could build up the whole batch in one go, e.g.
var sql = "DECLARE #RowId INT;" +
"INSERT INTO MyTable (Column1, Column2, ...) VALUES (#P1, #P2, ...);" +
"SET #RowId = SCOPE_IDENTITY();" +
"INSERT INTO MyOtherTable (Column1, ...) VALUES (#P3, #P4, ...);";
This may not be exactly the right syntax, and you may need to use SET NOCOUNT ON; at the start (my mind is rusty as I rarely use dynamic SQL) but it should get you on the right track.
The best way of doing this is the use SCOPE_IDENTITY() function in TSQL. This should be executed as part of the insert i.e.
SqlCommand cmd = new SqlCommand(#"
INSERT INTO T (Name) VALUES(#Name)
SELECT SCOPE_IDENTITY() As TheId", conn);
cmd.AddParameter("#Name", SqlDbType.VarChar, 50).Value = "Test";
int tId = (int)cmd.ExecuteScalar();
Alternatively you can assign SCOPE_IDENTITY() to a variable to be used in successive statements. e.g.
DECLARE #T1 int
INSERT INTO T (Name) VALUES('Test')
SELECT #T1 = SCOPE_IDENTITY()
INSERT INTO T2 (Name, TId) VALUES('Test', #T1)
If you are just using SQL then check Duncan's answer. If however you are using LINQ then you can create the entity, save it to the DB and the ID parameter will be populated automatically.
Given a user entity and a user table it might look like this:
using(var db = new DataContext()) {
var user = new User { Name = "Jhon" };
db.Users.InsertOnSubmit(user);
db.SubmitChanges();
/* At this point the user.ID field will have the primary key from the database */
}

Categories

Resources