ExecuteNonQuery silently failed without any errors - c#

UPDATE: my code is behaving as expected by there was a typo in the stored procedure that was the reason it was failing.
I can't seem to figure out why or how to fix this because I am not getting any errors what I am getting is the return value is 0 which means fail.
Here is my .net code:
SqlParameter returnValue= new SqlParameter("returnValue", SqlDbType.Int);
returnValue.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(returnValue);
cmd.ExecuteNonQuery();
result = Convert.ToInt32(returnValue.Value); //1 success and 0 failed
My stored procedure:
CREATE PROCEDURE EmployeeUpdate
#employee_id BIGINT,
#name nvarchar(250)
AS
BEGIN
SET NOCOUNT ON
DECLARE #Result int
SET #Result = 0
UPDATE Employee
SET name = #name
WHERE employee_id = #employee_id
IF (##rowcount = 1)
BEGIN
SET #Result = 1
END
SET NOCOUNT OFF
RETURN #Result
END
So if I just execute the stored procedure from SQL Server Management Studio, it does update my row successfully without any error
EXEC EmployeeUpdate 34,'John John'
Return Value = 1

Replace the following
CREATE PROCEDURE EmployeeUpdate
#employee_id BIGINT,
#name nvarchar(250)
AS
BEGIN
SET NOCOUNT ON
With Following
CREATE PROCEDURE EmployeeUpdate
#employee_id BIGINT,
#name nvarchar(250)
AS
BEGIN
SET NOCOUNT OFF
SET NOCOUNT ON is indicating that number of rows effect by T-SQL will
not be returned
SET NOCOUNT OFF mean that number of rows effect by
T-SQL will be returned.

I would suggest to remove returnValue parameter altogether and just use the return value of ExecuteNonQuery() method instead:
int rowsAffected = cmd.ExecuteNonQuery();
result = rowsAffected == 1 ? 1 : 0;
Stored procedure:
CREATE PROCEDURE EmployeeUpdate
#employee_id BIGINT,
#name nvarchar(250)
AS
BEGIN
UPDATE Employee
SET name = #name
WHERE employee_id = #employee_id
END

Related

Use if statement and return value to c# from a stored procedure in SQL Server

All I want to do is check if a name exists in a given table in my database or not but I am getting multiple returns from the stored procedure causing an exception.
This is the stored procedure I am using in SQL Server:
CREATE OR ALTER PROCEDURE ContactExists
#Name varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #result bit = 0
DECLARE #name varchar(50) = '';
SET #name = (SELECT Name FROM Table)
IF (#name = #Name)
BEGIN
SET #result = 1
RETURN #result
END
RETURN #result
END
GO
And this is the method I am using in C#:
SPstr = "dbo.ContactExists";
SqlCommand cmd = new SqlCommand(SPstr, connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Name", Name);
var returnValue = cmd.Parameters.Add("#result", SqlDbType.Int);
returnValue.Direction = ParameterDirection.ReturnValue;
cmd.ExecuteNonQuery();
return (int)returnValue.Value;
I am getting multiple returns from the stored procedure causing an exception.
I suspect you mean you're getting this:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
which is going to arise from this:
set #name = (SELECT Name from Table)
if Table has more than one row. Ensure the subquery (SELECT Name from Table) returns at most one row (use a WHERE on the pk, use MAX etc..)
Don't use the return value from stored procedures to return data. It's an old and mostly obsolete way to signal success or failure of the proc. So either use an output parameter:
CREATE OR ALTER PROCEDURE ContactExists
#Name varchar(50), #result bit output
AS
BEGIN
SET NOCOUNT ON;
set #result = 0;
if exists (SELECT * FROM SomeTable where name = #Name)
begin
set #result = 1;
end
END
or a resultset
CREATE OR ALTER PROCEDURE ContactExists
#Name varchar(50)
AS
BEGIN
SET NOCOUNT ON;
declare #result bit = 0;
if exists (SELECT * FROM SomeTable where name = #Name)
begin
set #result = 1;
end
select #result result;
END

Why I get exception when I call stored procedure?

I am using Entity Framework 6 and Microsoft SQL Server 2012.
Here is my stored procedure:
ALTER PROCEDURE SPDeleteRegion
#siteId int,
#regionId int
AS
BEGIN
SET NOCOUNT ON;
DECLARE #isDeleted BIT
IF EXISTS (SELECT 1 FROM SiteObjects WHERE SiteRegionId = #regionId)
BEGIN
SET #isDeleted = 0 ; --not deleted
RETURN #isDeleted;
END
ELSE
BEGIN
--do what needs to be done if not
DELETE FROM SiteRegions
WHERE Id = #regionId;
SET #isDeleted = 1; -- deleted
RETURN #isDeleted;
END
END
Here how I call the stored procedure in C#:
var t = _context.Database.SqlQuery<bool>("SPDeleteRegion #siteId, #regionId",
new SqlParameter("#siteId", siteId),
new SqlParameter("#regionId", regionId));
On the line of code above I get this exception:
The data reader has more than one field. Multiple fields are not valid for EDM primitive or enumeration types.
Any idea why I get the excewption and how to fix it?
Your procedure doesn't selecting anything. Change it like this:
ALTER PROCEDURE SPDeleteRegion
-- Add the parameters for the stored procedure here
#siteId int,
#regionId int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE
#isDeleted BIT
IF EXISTS (SELECT 1 FROM SiteObjects WHERE SiteRegionId = #regionId)
BEGIN
SET #isDeleted = 0 ; --not deleted
SELECT #isDeleted [IsDeleted]; --HERE
END
ELSE
BEGIN
--do what needs to be done if not
DELETE FROM SiteRegions WHERE Id = #regionId;
SET #isDeleted = 1;--deleted
SELECT #isDeleted [IsDeleted]; -- AND HERE
END
END

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;

SQl Transactions - query doesnt return value as expected

tblParent
pid(int) name deleted(bit)
1 abc 0
2 def 0
tblChild
cid(int) name pid(ForeignKey)
1 aaa 1
2 bbb 1
When a record from tblParent is being deleted, it should check for any child records. If yes, rollback & return 0. If no, then update the deleted column to '1' and return 1.
Basically, doing a soft delete
The SP works fine. All I need is to know the status as 0 or 1 based upon the action that took place. How should it be done. I would call this store procedure from c#, linq to entities to get the status.
something like:
public int somefuntion() //returning a string is also fine..
{
return MYDB.SoftDelete(parameters.....);
}
EDIT:
ALTER PROCEDURE SoftDelete
(
#TableName nvarchar(50), #ColName nvarchar(50),
#Id nvarchar(50)
)
AS
BEGIN
DECLARE #qry nvarchar(500)
SELECT #qry = 'begin transaction
delete '+#tablename+' where '+#colname+'='+#id+'
if(##Error <> 0)
Begin
--select 0
End
else
Begin
rollback transaction
update '+#tablename+' set deleted = 1 where '+#colname+' = '+#id+'
--select = 1
end'
EXECUTE sp_executesql #qry
END
Try this:
Declare #status nvarchar(50),#tablename nvarchar(50), #colname nvarchar(50),
#id nvarchar(50), #qry nvarchar(500)
set #tablename = 'person'
set #colname = 'id'
set #id = '15'
begin try
begin transaction
set #qry='delete '+#tablename+' where '+#colname+'=#id'
execute sp_executesql #qry,N'#id nvarchar(50)',#id=#id
rollback
--NO FK violation.So begin another transaction and soft delete
begin transaction
set #qry='update '+#tablename +' set deleted=1 where '+#colname+'=#id'
execute sp_executesql #qry,N'#id nvarchar(50)',#id=#id
commit
select 1
end try
begin catch
print(Error_Message())
--FK violation.Do nothing.Return 0
select 0
end catch
In your script the #status variable is not accessible inside your sql statement you build because "execute sp_executesql #qry" will be executing in different space. Instead use select n" in replace to "set #status = 0" and "set #status = 1"
Try this
Declare #tablename nvarchar(50), #colname nvarchar(50),
#id nvarchar(50), #qry nvarchar(500)
set #tablename = 'tblParent'
set #colname = 'pid'
set #id = '1'
select #qry = 'begin transaction
delete '+#tablename+' where '+#colname+'='+#id+'
if(##Error <> 0)
Begin
select 0
End
else
Begin
rollback transaction
update '+#tablename+' set deleted = 1 where '+#colname+' = '+#id+'
select 1
end
execute sp_executesql #qry

update query returns -1 value eventhough the data is updated in database

update query returns -1 value eventhough the data is updated in database . I am using sql server 2005 stored procedure with c#.
My stored procedure is as follows...
ALTER procedure [dbo].[sp_changepwd]
(
#Cust_Id varchar(50),
#Password varchar(50),
#OldPassword varchar(50),
#Username varchar(50)
)
as
Begin
SET NOCOUNT ON
Begin Tran
update
Customer_Utility_Reg_M_Tbl
set
Password=Convert(varbinary(50),#Password)
where
Cust_Id=#Cust_Id and Password=#OldPassword and Username=#Username
IF ##ERROR = 0
COMMIT TRAN
ELSE
ROLLBACK TRAN
RETURN (##ERROR)
END
SET NOCOUNT OFF when you SET NOCOUNT ON it doesnt report the number of record affected

Categories

Resources