I call a stored procedure from my c# code to insert a row into a table. My problem is that i always get 0 affected rows. Here are the codes
Stored procedure code
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `AddInfo`(
IN _activationDate datetime,
IN _organization varchar(100),
IN _email varchar(45),
IN _tableName varchar(35))
BEGIN
set #sqlquery = concat('insert into ', _tableName, ' values (?, ?, ?)');
prepare stmt from #sqlquery;
set #activationDate = _activationDate;
set #orgaization = _organization;
set #email = _email;
execute stmt using #activationDate, #orgaization, #email,;
deallocate prepare stmt;
END
C# code
using (MySqlConnection conn = new MySqlConnection(connStr))
{
string spName = "AddInfo";
MySqlCommand cmd = new MySqlCommand(spName, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#_activationDate", activationDate);
cmd.Parameters.AddWithValue("#_organization", organization);
cmd.Parameters.AddWithValue("#_email", email);
cmd.Parameters.AddWithValue("#_tableName", tableName);
conn.Open();
int rowsAffected = cmd.ExecuteNonQuery();
bool added = rowsAffected == 1 ? true : false;
conn.Close();
return added;
}
when i run this code the row is successfully added to the table, but rowsAffected is always 0. Where is my problem? Thank you
Related
I have written this Stored Procedure:
ALTER PROCEDURE [cairs].[sp_SaveR]
-- Add the parameters for the stored procedure here
#fname nvarchar(50),
#lname nvarchar(50),
#mname nchar(10),
#sigDate date
AS
BEGIN
SET NOCOUNT ON;
insert into tUser
(fname,
lname,
mname,
sigDate
)
values
(
#fname,
#lname,
#mname,
#sigDate)
select SCOPE_IDENTITY()
END
This is the c# code I use to connect to it:
try
{
using (SqlConnection conn = new SqlConnection(cCon.getConn()))
{
using (SqlCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "sp_SaveR";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#fname", fName));
cmd.Parameters.Add(new SqlParameter("#lname", lName));
cmd.Parameters.Add(new SqlParameter("#mname", mName));
cmd.Parameters.Add(new SqlParameter("#sigDate", sigDate));
int userID = (int)cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
throw(ex);
}
My userID is always returning -1, even though the records are successfully inserted into the DB table. Why does this happen?
ExecuteNonQuery discards the result set. The number it returns is usually the number of rows affected, but it isn't something you can really rely on. In your case, it returns -1 because you're executing a stored procedure, it would return 1 if you inlined the SQL.
You want to use ExecuteScalar instead, which reads the first column from the first row in the first result set.
This is working as designed. The return value is the number of modified rows. If you are calling a stored proc or selecting data the value will be -1.
From MSDN...
SqlCommand.ExecuteNonQuery
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
You should use output parameter to retrive id like as below.
ALTER PROCEDURE [cairs].[sp_SaveR]
-- Add the parameters for the stored procedure here
#fname nvarchar(50),
#lname nvarchar(50),
#mname nchar(10),
#sigDate date,
#NewId int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
insert into tUser
(fname,
lname,
mname,
sigDate
)
values
(
#fname,
#lname,
#mname,
#sigDate)
select #NewId = SCOPE_IDENTITY()
END
In C#:
try
{
using (SqlConnection conn = new SqlConnection(cCon.getConn()))
{
using (SqlCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "sp_SaveR";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#fname", fName));
cmd.Parameters.Add(new SqlParameter("#lname", lName));
cmd.Parameters.Add(new SqlParameter("#mname", mName));
cmd.Parameters.Add(new SqlParameter("#sigDate", sigDate));
cmd.Parameters.Add("#NewId", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
int userId = Convert.ToInt32(cmd.Parameters["#NewId"].Value);
}
}
}
catch (Exception ex)
{
throw(ex);
}
I have a problem while inserting records into SQL Server.
The string from C# doesn't show up in SQL Server as I'm inserting the sql just insert the first char
Example: If I insert 22222 in the data base just the first 2 inserted
Note I'm using a stored procedure for my first time.
This is my code:
public void insert_workshop(DateTime Pdate, string PTime, string PDesc, byte[] Img)
{
SqlCommand cmd = new SqlCommand("[InsertWorkShops]", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#WorkshopsDate", SqlDbType.Date).Value = Pdate;
cmd.Parameters.Add("#Time", SqlDbType.NVarChar).Value = PTime;
cmd.Parameters.Add("#WorkshopsDescription", SqlDbType.NVarChar).Value = PDesc;
cmd.Parameters.Add("#WorkshopsImage", SqlDbType.Image).Value = Img;
cmd.Parameters.Add("#CreatedBy", SqlDbType.NVarChar).Value = 1;
try
{
cmd.ExecuteNonQuery();
Msg = "Add Done ";
}
catch
{
Msg = "Error While Adding";
}
WorkShopTransactions Ws = new WorkShopTransactions();
Ws.insert_workshop(WorkShopDT.Value, txtWorshopTime.Text.ToString(),
txtWorkshopDescriptions.Text.ToString(), img);
T-SQL:
ALTER PROCEDURE [dbo].[InsertWorkShops]
#WorkshopsDate date,
#Time nvarchar,
#WorkshopsDescription nvarchar,
#WorkshopsImage image,
#CreatedBy int
AS
BEGIN
SET NOCOUNT ON;
insert into Workshops
values(#WorkshopsDate, #Time, #WorkshopsDescription, #WorkshopsImage, #CreatedBy)
END
In the stored procedure, you have declared your nvarchar parameters without a length. They default to nvarchar(1).
I have a stored procedure which returns new ids.
create proc [dbo].[WriteIT]
(#deg nvarchar(max))
as
DECLARE #s nvarchar(max)
set #s = 'INSERT INTO test OUTPUT inserted.ID VALUES '
set #s += #deg
exec (#s)
How can I get that multiple results of stored procedures into a int[]?
string con = "Server=.;Database=Adb;Trusted_Connection=True";
SqlConnection connet = new SqlConnection(con);
SqlCommand cm = new SqlCommand("WriteIT", connet);
cm.CommandType = System.Data.CommandType.StoredProcedure;
bd = new StringBuilder();
string veri = "({0}),";
string sablon = "'{0}','{1}'";
for (int i = 0; i < 50; i++)
{
bd.Append(string.Format(veri, string.Format(sablon, new Random().Next(0, 100000).ToString(), new Random().Next(0, 100000).ToString())));
}
cm.Parameters.AddWithValue("#deger", bd.ToString().Substring(0, bd.Length - 1));
if (connet.State == System.Data.ConnectionState.Closed)
connet.Open();
string a = cm.ExecuteScalar();
ExecuteScalar is meant to return only the first column of the first row from the result..
If your SProc would return more than one value, you could use the ExecureReader() method.
SqlConnection sqlConnection1 = new SqlConnection("Your Connection String");
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = "StoredProcedureName";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
reader = cmd.ExecuteReader();
// Data is accessible through the DataReader object here.
sqlConnection1.Close();
You should also read on Random class. You should use the same instance to generate numbers.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Usp_CRMEntryInsert]
#custnam nvarchar(250),
#proj nvarchar(255),
#projid int,
#contact nvarchar(100),
#updfile nvarchar(150),
#vtype nvarchar(100),
#sts varchar(15),
#recsts varchar(1),
#entryid int,
#entrydate datetime,
#dataentrydate datetime
AS
BEGIN
SET NOCOUNT ON;
insert into CRMEntry (custnam,Proj,projid,contact,updfile,vtype,status,rec_status,entered_id,entered_date,entry_date) values (#custnam,#proj,#projid,#contact,#updfile,#vtype,#sts,#recsts,#entryid,#entrydate,#dataentrydate)
select scope_identity()
This Scope_identity() return max value
maxid = cmd.ExecuteScalar()
i have that code using LINQ to call a stored procedure to save some data into database then return two variables from the stored procedure.
[ASP.NET code]
dbDataContext dbo = new dbDataContext();
dbo.AddNewDoctor(doctorName, email, password, ref DocId, ref result);
[SQL]
create PROCEDURE [dbo].[AddNewDoctor]
#doctorname nvarchar(100),
#email nvarchar(100),
#password nvarchar(MAX),
#docId int out,
#Result int out
AS
BEGIN
SET NOCOUNT ON;
declare #idCounter int
select #idCounter = count(*) from dbo.doctors
if EXISTS (select * from dbo.doctors where e_mail = #email)
begin
SET #Result = -1
set #docId= 0
end
else
begin
INSERT INTO [dbo].[doctors]
([doctor_id]
,[doctorname]
,[e_mail]
,[password]
VALUES
((#idCounter +1)
,#docotorname
,#email
,#password
)
SET #Result = 1
set #docId= (#idCounter + 1)
end
END
this code work very well what i want to do now to use ADO instead of LINQ, the problem with me is that i can't pass the ref variable as in LINQ so how can i do it using ADO
You'll have to do something like this. Use ParameterDirection
SqlParameter output = new SqlParameter(paramName, dbType);
output.Direction = ParameterDirection.Output;
command.Parameters.Add(output);
In your case you've to use SqlDbType.Int. Use Value property to read return value.
SqlParameter output = new SqlParameter(paramName, SqlDbType.Int);
output.Direction = ParameterDirection.Output;
command.Parameters.Add(output);
int Result = (int) output.Value; or int? Result = (int?) output.Value;
Try this
using (SqlConnection con = new SqlConnection("Your connection string"))
{
con.Open();
SqlCommand mycommand = new SqlCommand();
mycommand.Connection = con;
mycommand.CommandText = "dbo.AddNewDoctor";
mycommand.CommandType = CommandType.StoredProcedure;
mycommand.Parameters.AddWithValue(doctorName);
mycommand.Parameters.AddWithValue(email);
mycommand.Parameters.AddWithValue(password);
mycommand.Parameters.AddWithValue(ref DocId);
mycommand.Parameters.AddWithValue(ref result);
mycommand.ExecuteNonQuery();
}
Hope this helps thanks.
Refer to this article, there is an working example:
http://csharp-guide.blogspot.de/2012/05/linq-to-sql-call-stored-procedure-with_25.html
I m creating new user registration moduleand for that i wrote following stored proc.
PROCEDURE [dbo].[addNewUser]
-- Add the parameters for the stored procedure here
#usertype VarChar(10),
#useremail VarChar(70),
#userpass VarChar(20),
#fullname VarChar(70),
#city VarChar(70),
#state Int,
#allowAlerts Bit,
#allowLetter Bit,
#aboutMe NVARCHAR(160)
As
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
if ((select count(user_info._id) from user_info where useremail like #useremail) = 0)
BEGIN
Insert Into user_info
(usertype,useremail,userpass,fullname,city,[state],allowAlerts,allowLetters,aboutMe)
Values
(
#usertype,
#useremail,
#userpass ,
#fullname,
#city,
#state,
#allowAlerts,
#allowLetter,
#aboutMe
)
Select ##IDENTITY as NewID
END
Else
BEGIN
Print '-1'
END
And following is the simple ASP.net C# Code that I try to use
public int registerNewUser(string usertype, string useremail, string userpass, string fullname, string city, string state, string allowAlerts, string allowLetter, string aboutMe)
{
con = new SqlConnection(connectionString);
cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "addBlogEntry";
cmd.Parameters.Add("#usertype", SqlDbType.VarChar).Value = usertype;
cmd.Parameters.Add("#useremail", SqlDbType.VarChar).Value = useremail;
cmd.Parameters.Add("#userpass", SqlDbType.VarChar).Value = userpass;
cmd.Parameters.Add("#fullname", SqlDbType.VarChar).Value = fullname;
cmd.Parameters.Add("#city", SqlDbType.VarChar).Value = city;
cmd.Parameters.Add("#state", SqlDbType.VarChar).Value = Convert.ToInt16(state);
cmd.Parameters.Add("#allowAlerts", SqlDbType.VarChar).Value = Convert.ToInt16(allowAlerts);
cmd.Parameters.Add("#allowLetter", SqlDbType.VarChar).Value = Convert.ToInt16(allowLetter);
cmd.Parameters.Add("#aboutMe", SqlDbType.VarChar).Value = aboutMe;
try
{
if (con.State != ConnectionState.Open)
con.Open();
cmd.ExecuteNonQuery();
con.Close();
con.Dispose();
// some code to be written here so that i can return userID(success) or -1(if that username is already registered)
return 0;
}
catch (Exception Ex)
{
con.Close();
con.Dispose();
return 0;
}
}
Through my C# code i want to return either auto generated userId which my stored procedures returns to me or if user alrady exists than i want to return -1
Please tell how to do this?
Thanks in advance :)
Yes, you can use ExecuteScalar() and change
Print '-1'
into
Select -1 as NewID
First of all, you should use SELECT SCOPE_IDENTITY() inside your stored proc to retrieve the new ID value (##IDENTITY can return false results).
And yes, if you want to get the result back, you need to call either .ExecuteScalar() or .ExecuteReader() and then read that value back.
And while you're at it - I'd also recommend putting your SqlConnection and SqlCommand objects into using blocks - so instead of your code, use this:
using(con = new SqlConnection(connectionString))
using(cmd = new SqlCommand(con))
{
..... // put the rest of your code here
}
If you want to create an output parameter for your stored proc, and set it to the new key you can access it that way. ExecuteNonQuery will return the number of rows affected, so that can be used as well. Something like this:
cmd.Parameters.Add("#uniquID", SqlDbType.Int).Direction = ParameterDirection.Output;
// Your other code...
var result = cmd.ExecuteNonQuery();
// Your other code...
return (result == 1) ? (int)cmd.Parameters["#uniquID"].Value : -1;