get the id of the last inserted row in - c#

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.

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.

Parameter passing to stored procedures in SQL

I have a SQL procedure that I'm calling from my c# code.
cmd = new SqlCommand("InsertData", con, transaction);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#IP_No", SqlDbType.VarChar, 50);
cmd.Parameters["#IP_No"].Value = data.IP_No;
result = cmd.ExecuteNonQuery().ToString();
This is my procedure:
(
#IP_No varchar(15),
#Indent_No varchar(20)
)
AS
BEGIN
set #Indent_No = (SELECT IndentId from IdTable)
INSERT INTO InsertData(IP_No,Indent_No)
VALUES(#IP_No,#Indent_No)
Update IdTable set IndentId=IndentId+1;
END
Basically, I want my ID to be pulled from a database where I keep incrementing it.
It throws this error:
Procedure or function expects parameter #Indent_No which was not
supplied.
Please Help!
As you use #Indent_No only internally within the stored procedure, you don't need to declare it as an input parameter. You need to declare it within the body of your stored procedure
CREATE PROCEDURE InsertData
(
#IP_No varchar(15)
)
AS
BEGIN
DECLARE #Indent_No varchar(20)
set #Indent_No = (SELECT IndentId from IdTable)
INSERT INTO InsertData(IP_No,Indent_No)
VALUES(#IP_No,#Indent_No)
Update IdTable set IndentId=IndentId+1;
END

Create stored procedure to add with auto increment as its primary field?

I am trying to insert Data into my Sql-Server database though C#. I'm Calling a stored procedure and then would like it to add. I'm not sure what changes to make, but ultimately i would like it done in the stored procedure.
My Stored procedure now:
CREATE PROCEDURE [dbo].[InsertTagProcdure]
#TagID int,
#Value nvarchar(200),
#TagCount nvarchar(200)
AS
IF NOT EXISTS (SELECT NULL FROM Tag
WHERE #TagID = #TagID)
BEGIN
INSERT INTO
Tag
(TagID,Value,TagCount)
VALUES
(#TagID,#Value,#TagCount)
END
And my C# Code:
int TagID = int.Parse(txtTagID.Text); //This should fall away so auto increment.
String Value = txtValue.Text;
int TagCount = int.Parse(txtCount.Text);
using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "InsertTagProcdure";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#TagID", TagID);
cmd.Parameters.AddWithValue("#Value", Value);
cmd.Parameters.AddWithValue("#TagCount", TagCount);
cmd.ExecuteNonQuery();
}
The Table Create i used: //Cant change this its what the boss gave me.
CREATE TABLE [dbo].[Tag](
[TagID] [int] IDENTITY(1,1) NOT NULL,
[Value] [varchar](200) NOT NULL,
[TagCount] [varchar](200) NULL,
CONSTRAINT [PK_Tag] PRIMARY KEY CLUSTERED
(
[TagID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Ideally you would just make TagID an identity field by changing the table definition. If you can't do that, next best would be:
CREATE PROCEDURE [dbo].[InsertTagProcdure]
#Value nvarchar(200),
#TagCount nvarchar(200)
AS
BEGIN
BEGIN TRANSACTION
DECLARE #TagID int;
SELECT #TagID = coalesce((select max(TagID) + 1 from Tag), 1)
COMMIT
INSERT INTO
Tag
(TagID,Value,TagCount)
VALUES
(#TagID,#Value,#TagCount)
END
The transaction ensures that you don't end up with unique TagIDs and the coalesce handles the special case where the table is empty and gives an initial value of 1.
EDIT:
Based on the change to your original question, the table already has an identity column so your stored procedure should be:
CREATE PROCEDURE [dbo].[InsertTagProcdure]
#Value nvarchar(200),
#TagCount nvarchar(200)
AS
BEGIN
INSERT INTO Tag (Value,TagCount) VALUES (#Value,#TagCount)
END
and your C# code should be
int TagID = int.Parse(txtTagID.Text); //This should fall away so auto increment.
String Value = txtValue.Text;
int TagCount = int.Parse(txtCount.Text);
using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "InsertTagProcdure";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Value", Value);
cmd.Parameters.AddWithValue("#TagCount", TagCount);
cmd.ExecuteNonQuery();
}
You want to set the tag table up so that it uses the identity property. See here: http://msdn.microsoft.com/en-us/library/aa933196(v=sql.80).aspx.
Then you can drop TagId from the procedure, the insert statement in the procedure and the c# code.
It then becomes something like this:
CREATE PROCEDURE [dbo].[InsertTagProcdure]
#Value nvarchar(200),
#TagCount nvarchar(200)
AS
BEGIN
INSERT INTO
Tag
(Value,TagCount)
VALUES
(#Value,#TagCount)
END
C# Code:
String Value = txtValue.Text;
int TagCount = int.Parse(txtCount.Text);
using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "InsertTagProcdure";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Value", Value);
cmd.Parameters.AddWithValue("#TagCount", TagCount);
cmd.ExecuteNonQuery();
}
the statement WHERE #TagID = #TagID will always be true, because your comparing the same values.
I think your looking for this (assuming TagID is your AUTO-ID field);
CREATE PROCEDURE [dbo].[InsertTagProcdure]
#TagID int,
#Value nvarchar(200),
#TagCount nvarchar(200)
AS
BEGIN
IF NOT EXISTS (SELECT TagID FROM Tag WHERE TagID = #TagID)
BEGIN
INSERT INTO
Tag
(Value,TagCount)
VALUES
(#Value,#TagCount)
SET #TagID = ##IDENTITY
END
ELSE
BEGIN
UPDATE Tag
SET Value=#Value,
TagCount=#TagCount
WHERE TagID = #TagID
END
RETURN #TagID
END
You have to turn on 'Identity specification' in SQL Server on the appropriate column. Go to table design mode, select the column and in the bottom properties screen there is a property called 'Identity specification'.
After this, you can omit the TagId in your stored procedure. Sql Server will automatically assign an id to a new record.
If you want to know what that newly inserted id is (which I assume is your next question), you can use the function SCOPE_IDENTITY() in your stored procedure, which returns the id of the newly inserted record.

Select Cast (Scope_identity) and executescalar

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

Categories

Resources