How to Get IDENT_CURRENT result with c# ' s SqlCommand? - c#

I have a stored procedure in which I want to get the last inserted row for a specific table say table TbUsers , so in the end of it, I type that line:
select IDENT_CURRENT('TbUsers')
Now I want to get that result in C#, using SqlCommand; I pass these parameters to to the stored procedure:
SqlCommand command = new SqlCommand("InsertUsers", conn);
command.CommandType = System.Data.CommandType.StoredProcedure;
/* Insert in TbUsager */
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("#firstName" ,value.firstname),
new SqlParameter("#lastName",value.lastname),
new SqlParameter("#email",value.email),
new SqlParameter("#phoneNumber",value.phoneNumber),
new SqlParameter("#address",value.address),
new SqlParameter("#country",value.country),
new SqlParameter("#city",value.city),
new SqlParameter("#zipCode",value.zip_code)
};
command.Parameters.AddRange(parameters);
var rdr = command.ExecuteReader()
How can I get the returned result of the stored procedure?
Update
i have added this code :
// command.Parameters.AddRange(parameters);
var LastInsertedUsagerId = new SqlParameter("#lastInsertedUsagerId", System.Data.SqlDbType.Int);
LastInsertedUsagerId.Direction = ParameterDirection.Output;
command.Parameters.Add(LastInsertedUsagerId);
// var rdr = command.ExecuteReader();
var LastInsertedUsagerId2 = command.Parameters["#LastInsertedUsagerId"].Value;
but i still getting null as a result ?
Update2
this is my SP:
ALTER PROCEDURE [dbo].[InsertUsager]
-- Add the parameters for the stored procedure here
#Nom_Usager varchar(20),
#Prenom_Usager varchar(20),
#Email_Usager varchar(20),
#Telephone_Portable_Usager varchar(20),
#Adresse_Usager varchar(20),
#Pays_Usager varchar(20),
#Ville_Usager varchar(20),
#IdVille_Usager varchar(20),
#LastInserted_IdUsager int OUTPUT
AS
BEGIN
-- Insert a new usager
declare #IdinsertedUsager table(IdinsertedUsager int)
declare #IdAddressVillePayselse table(IdAddressVillePayselse int)
declare #newUsager int , #IdAddressVillePays int , #addressvp int,#IdCountry int,#IdVille int
Insert into TbUsager (IdTypeUsager,Nom_Usager,Prenom_Usager,Indic_Maj)
Output inserted.IdUsager into #IdinsertedUsager
values(1,#Prenom_Usager,#Nom_Usager,'P')
SELECT #newUsager = IdinsertedUsager FROM #IdinsertedUsager
/* some code */
select #LastInserted_IdUsager=IDENT_CURRENT('TbUsers')
END
and it works well when i execute it in sqlserver

Assuming you're returning the identity id correctly(as output parameter) in your SP, in your C# code you can retrieve it like this:
var id = command.Parameters["#id"].Value;
Change #id to the name of your output variable in SP.
Here's a link to see how to do it correctly in detail:
https://www.aspsnippets.com/Articles/Return-Identity-value-from-Stored-Procedure-in-SQL-Server.aspx

Solved, in addition to #Siavash is answer , in order to work we need to use : command.ExecuteNonQuery()
instead of command.ExecuteReader()
In this documentation we get the difference and when to use each one.

Related

Can't call stored procedure

I'm a beginner at C#. I can't call a stored procedure.
My stored procedure is this:
CREATE PROCEDURE USP_login
#us VARCHAR(20),
#pwd VARCHAR(20)
AS
BEGIN TRAN
BEGIN TRY
SELECT *
FROM dbo.KhachHang
WHERE tenDangNhap = #us AND matKhau = #pwd
END TRY
BEGIN CATCH
ROLLBACK TRAN
RETURN 0
END CATCH
COMMIT TRAN
RETURN 1
GO
In my C# code, I use this function to call the USP_login stored procedure but it doesn't work:
public bool loginStored(string us, string pwd)
{
object[] sqlParams =
{
new SqlParameter ("#userName", us),
new SqlParameter ("#passWord", pwd),
};
var rs = db.Database.SqlQuery<bool>("USP_login #userName, #passWord", sqlParams).SingleOrDefault();
return rs;
}
Error message in screenshot:
Looks like SELECT * ... is returning more than just a single bool. (Based on the query, clearly the table has at least two fields, tenDangNhap and matKhau.) But that's what you told the code to expect:
db.Database.SqlQuery<bool>(/.../)
Either select only the column you want:
SELECT SomeBooleanValue FROM dbo.KhachHang WHERE tenDangNhap=#us AND matKhau=#pwd
Or specify the correct type that can be expected for each record (which may be a custom class that you need to define):
db.Database.SqlQuery<SomeObjectType>(/.../)

Stored procedure doesn't return an int value

MySql Procedure Code:
CREATE DEFINER=`root`#`localhost` PROCEDURE `USP_CreateCliente`(IN nome_cliente VARCHAR(45))
BEGIN
Select 20;
INSERT INTO clienti ( nome_cliente )
VALUES ( nome_cliente );
Select id_cliente from clienti;
END
C# code in the controller page:
ClienteInfo CI = new ClienteInfo();
DboUser objdbo = new DboUser();
int id_cliente = 0;
CI.nome_cliente = txtNomeCliente.Text;
id_cliente = objdbo.CreateClienteInfo(CI);
DboUser class:
public int CreateClienteInfo(ClienteInfo CI)
{
int result;
MySqlConnection conn = new MySqlConnection();
DbConnection db = new DbConnection();
conn = db.ConnessioneDb();
MySqlCommand cmd = new MySqlCommand(Costanti.StoredProcedures.USP_CreateCliente, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#nome_cliente", CI.nome_cliente);
result = cmd.ExecuteNonQuery();
conn.Close();
return result;
}
I want my C# code to retrieve the id of my customer after inserting it into the database, so I can save it to the session and retrieve it again later in a page that will print a document with the customer's informations.
My id_cliente returns 0, do you notice any syntax error?
Did I do something wrong?
I'm 90% sure it's a problem dealing with the stored precedure tough, cause the customer is inserted correctly
Change this line
result = cmd.ExecuteNonQuery();
to
result = Convert.ToInt32(cmd.ExecuteScalar());
but you should also change your stored procedure because it doesn't return the last id generated for you by the AUTO_INCREMENT column id_cliente
CREATE DEFINER=`root`#`localhost` PROCEDURE `USP_CreateCliente`(IN nome_cliente VARCHAR(45))
BEGIN
INSERT INTO clienti ( nome_cliente ) VALUES ( nome_cliente );
Select LAST_INSERT_ID();
END
In MySql, to get the generated auto_increment value, you could use LAST_INSERT_ID(), next, your C# code don't need to use ExecuteNonQuery, which returns just the number of rows that you have changed, added or deleted, but you use ExecuteScalar which returns the first column of the first row of the last SELECT command executed by your stored procedure. (It is the SELECT LAST_INSERT_ID())
Also, to complete the answer, you don't really need a stored procedure for this kind of simple work. The advantages should be minimal while the problems related to a different piece of software to maintain are self evident.
Your C# code could be (removed the usage of your DbConnection class because it is not clear what it does)
public int CreateClienteInfo(ClienteInfo CI)
{
int result;
string cmdText = #"INSERT INTO clienti ( nome_cliente ) VALUES ( nome_cliente );
Select LAST_INSERT_ID();";
using(MySqlConnection conn = new MySqlConnection(....connectionstring .....))
using(MySqlCommand cmd = new MySqlCommand(cmdText, conn);
{
conn.Open()
cmd.Parameters.AddWithValue("#nome_cliente", CI.nome_cliente);
result = Convert.ToInt32(cmd.ExecuteScalar())
return result;
}
}
Here you use the possibility to pass batch commands to your MySql engine, meaning two commandtexts with the same MySqlCommand separating them with the semicolon

Calling a stored procedure with a parameter that is a table

I'm trying to call the below stored procedure but I am unsure on what to pass through one of the parameters (#UnsubscribeTypes) I've tried passing in a list but got a compile error. I'm using c#, Visual Studio 2010, web forms. Any ideas on what I should pass in when calling the stored procedure in my c# code (ado.net)?
Here is my stored procedure:
ALTER PROCEDURE [czone].[SetAccountEmailPreference]
(
#EmailAddress VARCHAR(255),
#UnsubscribeTypes dbo.ListOfIDs READONLY,
#SentEmailID INT = NULL
)
AS
SET NOCOUNT ON;
EXEC dbo.LogObjectExecution ##PROCID;
DECLARE #UnsubscribeID INT = (SELECT TOP 1 UnsubscribeID
FROM Email.dbo.Unsubscribe
WHERE EmailAddress = #EmailAddress
ORDER BY UnsubscribeID DESC);
-- Unsubscribe
IF ((SELECT COUNT(*) FROM #UnsubscribeTypes) > 0)
BEGIN
IF(#UnsubscribeID IS NULL)
BEGIN
-- ADD UNSUBSCRIBE
INSERT INTO Email.dbo.Unsubscribe (EmailAddress, CreatedDate)
VALUES (#EmailAddress, CURRENT_TIMESTAMP)
SET #UnsubscribeID = ##IDENTITY;
END
-- Remove current mappings
DELETE FROM Email.dbo.UnsubscribeTypeMapping
WHERE UnsubscribeFK = #UnsubscribeID;
-- Add new mappings
INSERT INTO Email.dbo.UnsubscribeTypeMapping (UnsubscribeFK, UnsubscribeTypeFK, SentEmailFK)
SELECT
#UnsubscribeID, ID, #SentEmailID
FROM
#UnsubscribeTypes;
END
-- Subscribe
ELSE IF (#UnsubscribeID IS NOT NULL)
BEGIN
DELETE FROM Email.dbo.Unsubscribe
WHERE UnsubscribeID = #UnsubscribeID;
END
dbo.ListOfIDs is a table type. First, find out the type in your database, then check columns. generate a datatable with rows containing the UnsubscribeTypeFK ids.
The ADO.net code (not compiled)
Creating table
DataTable dt = new DataTable("Items");
dt.Columns.Add("ID", typeof(int));
dt.Rows.Add(4);
Calling proc
con = new SqlConnection(conStr);
con.Open();
using (con) {
// Configure the SqlCommand and SqlParameter.
SqlCommand sqlCmd = new SqlCommand("czone.SetAccountEmailPreference", con);
sqlCmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParam = sqlCmd.Parameters.AddWithValue("#UnsubscribeTypes", _dt); // TVP
tvpParam.SqlDbType = SqlDbType.Structured; //tells ADO.NET we are passing TVP
//pass other parameters
sqlCmd.ExecuteNonQuery();
}
con.Close();
You will find more about Table-Valued parameters here

data insert using input output stored procedure

I am creating a web application using ASP.net C#. I have a booking form and I need to insert data into a table using a Stored Procedure. The table has several columns, out of which second column is a computed column. The Stored Procedure is set up to insert the data and fetch the value from the second column after insert. Below is the code for Stored Procedure:
Create Procedure sp_InsertCashPooja
#FirstName varchar(100),
#LastName varchar(100),
#TelNo bigint,
#Star char(50),
#Rasi char(50),
#Gothram char(50),
#PDMID int,
#PayMode bit,
#PujaName char(50),
#DonateAmt decimal(19,2),
#RcptNo varchar(25) output
as
Begin
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION
if #PujaName != 'DONATION'
Begin
INSERT INTO PoojaDetails (FirstName, LastName, TelNo, Star, Rasi, Gothram, PoojaDietyMasterID, PayMode) values (#FirstName,#LastName,#TelNo,#Star,#Rasi,#Gothram,#PDMID,#PayMode)
End
if #PujaName = 'DONATION'
Begin
DECLARE #isDonate int = 0;
INSERT INTO PoojaDetails (FirstName, LastName, TelNo, Star, Rasi, Gothram, PoojaDietyMasterID, PayMode, isDonate, DonateAmount) values (#FirstName,#LastName,#TelNo,#Star,#Rasi,#Gothram,#PDMID,#PayMode, #isDonate, #DonateAmt)
End
Select #RcptNo = max(ReceiptNo) from PoojaDetails
Return #RcptNo
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF (##TRANCOUNT > 0)
ROLLBACK TRANSACTION
END CATCH
SET NOCOUNT OFF;
End
I would like to insert data on the click of a button: I was able to figure out the below code....
protected void btnSave_Click(object sender, EventArgs e)
{
frmFirstName = txtFirstName.Text.Trim().ToUpper();
frmLastName = txtLastName.Text.Trim().ToUpper();
frmPhoneNo = Convert.ToInt32(txtPhoneNo.Text.Trim());
frmNakshatra = Convert.ToString(cmbNakshatra.SelectedItem).Trim();
frmRasi = Convert.ToString(cmbRasi.SelectedItem).Trim();
frmGothram = Convert.ToString(cmbGothram.SelectedItem).Trim();
frmPujaName = Convert.ToString(cmbPujaName.SelectedItem).Trim();
using (SqlConnection connection = new SqlConnection())
{
if (frmPayMode == "Cash")
{
if (frmPujaName == "DONATION")
{
SqlDataAdapter CashAdapter = new SqlDataAdapter();
CashAdapter.InsertCommand = new SqlCommand("sp_InsertCashPooja", connection);
CashAdapter.InsertCommand.CommandType = CommandType.StoredProcedure;
Please help.... I want to capture the returning RcptNo and later intend to call another ASPX page and pass the value using a Query String.
Thanks
Use simple SqlCommand for calling your SP
connection.Open();
var cmd = new SqlCommand("sp_InsertCashPooja", connection);
cmd.Parameters.AddWithValue("FirstName", frmFirstName);
// Add all the others parameters in same way
var id = (int)cmd.ExecuteScalar();
connection.Close();
Change the return variable to:
Select #RcptNo = SCOPE_IDENTITY()
It will return the identity number created for the inserted record within this procedure.
use sql parameter..
connection = ConfigurationManager.AppSettings["mycon"];
SqlParameter[] para = new SqlParameter[2];
para[0] = new SqlParameter("#stored procedure column name", string name);
para[1] = new SqlParameter("#stored procedure column name", string name);

Ado.net ExecuteScalar() returning null

I am executing a stored procedure in c# (through vs2008) using ado.net with an ExecuteScalar command. The stored proc returns the pkey of the new record entered, but ExecuteScalar is returning null. I look in the database and a record has indeed been added. I could use an output parameter to get the value, but then I won't know why this didn't work.
When I execute the sp in ssms, the pkey is returned.
What am I doing wrong?
Here is the C# code:
public int SaveNewPerson(EPerson ePerson)
{
int newPersonPkey;
SqlConnection cn = new SqlConnection(cnn.PersonData);
using (cn)
{
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "People.dbo.AddNewPerson";
cmd.Parameters.Add("#LastName", SqlDbType.VarChar, 150).Value = ePerson.LastName;
cmd.Parameters.Add("#FirstName", SqlDbType.VarChar, 150).Value = ePerson.FirstName;
cn.Open();
object result = cmd.ExecuteScalar();
newPersonPkey = int.Parse(result.ToString());
cn.Close();
}
catch (Exception e)
{
// call error method
throw new Exception(e.Message + " save new Person error ");
}
}
return newPersonPkey;
}
And this is the sp:
PROCEDURE [dbo].[AddNewPerson]
#FirstName varchar(50)
,#LastName varchar(50)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [People].[dbo].[Persons]
(
[FirstName]
,[LastName]
)
VALUES
(
#FirstName
,#LastName
)
declare #persons_PKey int
set #persons_PKey = ##IDENTITY
return #persons_PKey
end
The ExecuteScalar method returns the first field of the first record of the result, but as your query doesn't produce a result, it will return null.
You can either select the value instead of returning it from the stored procedure, or add a parameter with the direction set to ParameterDirection.ReturnValue to catch what the stored procedure returns.
Try changing the Stored Procedure to use a Select Statement to return the identity instead of using a return like this:
SELECT CAST(scope_identity() AS int)
Thus changing your procedure to:
PROCEDURE [dbo].[AddNewPerson]
#FirstName varchar(50)
,#LastName varchar(50)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [People].[dbo].[Persons]
(
[FirstName]
,[LastName]
)
VALUES
(
#FirstName
,#LastName
)
SELECT CAST(scope_identity() AS int)
end
From the documentation of the ExecuteScalar() on MSDN it says that it will return the first column of the first row in the result set or null otherwise if the result set is empty.

Categories