Check for duplicate emailid - c#

I am checking for a dupliacte emaild using stored proc
ALTER procedure [dbo].[Insertreg]
( #id int output,#FirstName varchar (50),#LastName varchar(50) ,#Dob datetime,
#Gender varchar(20) ,#MobileNo nchar(10) ,#Country varchar(50) ,
#State varchar (50),#EmailId varchar (50),#Password nchar (15),#result int output
)
as
begin
if exists(select EmailId from Profile_Master where EmailId=#EmailId)
set #result=0
else
begin
set #result=1
insert into Profile_Master(FirstName,LastName,Dob,Gender,MobileNo,Country,State,EmailId,Password)
values
(#FirstName,#LastName,#Dob,#Gender,#MobileNo,#Country,#State,#EmailId,#Password)
set #id=SCOPE_IDENTITY()
return
end
end
code behind
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
var id = cmd1.ExecuteNonQuery();
but when i debug if emailid exists i am getting id value as -1 how can i resolve this?

Using ExecuteNonQuery with StoredProc returns -1. That's the expected behaviour.
Change your code to
if exists(select EmailId from Profile_Master where EmailId=#EmailId)
select 0 as result
else
select 1 as result
C#, you don't need to pass parameter here anymore
var id = cmd1.ExecuteScalar();
Since you are using OUTPUT parameter, you can also use #Pilgerstorfer Franz's approach

This is the expected behaviour for ExecuteNonQuery.
Your query is not affecting any rows.
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 get the result as follows:
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
cmd1.ExecuteNonQuery();
var id = result.Value;

Please try:
cmd1.ExecuteScalar();
var id=Convert.ToInt32(result.Value);

id is not an Id but just the number of affected rows since you're using ExecuteNonQuery instead of ExecuteScalar You should check result after ExecuteNonQuery to get the output variable.
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
int numberOfAffectedRecords = (int)cmd1.ExecuteNonQuery();
// now result should have the output variable
If you want to have the newly created ID, you should use ExecuteScalar:
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
int newID = (int)cmd1.ExecuteScalar();
// now result should have the output variable

Calling ExecuteNonQuery() will return the number of rows affected. As you did add an outputParameter you should access this one.
// access an output parameter
cmd1.ExecuteNonQuery();
var id = cmd1.Parameters["#result"].Value;
// OR: get the returnValue of a SP
var id = cmd1.ExecuteScalar();
EDIT
What about using this version of your sp
ALTER procedure [dbo].[Insertreg]
( #FirstName varchar (50),#LastName varchar(50) ,#Dob datetime,
#Gender varchar(20) ,#MobileNo nchar(10) ,#Country varchar(50),
#State varchar (50),#EmailId varchar (50),#Password nchar (15))
as
begin
if exists(select EmailId from Profile_Master where EmailId=#EmailId)
select -1;
else
begin
insert into Profile_Master(FirstName,LastName,Dob,Gender,MobileNo,Country,State,EmailId,Password)
values (#FirstName,#LastName,#Dob,#Gender,#MobileNo,#Country,#State,#EmailId,#Password)
select SCOPE_IDENTITY();
end
end
And afterwars only use
// no need for any output Parameters here...
int id = int.Parse(cmd1.ExecuteScalar().ToString())
to access your id value. Value will be greater than -1 if given mail is unique and -1 in case email already exists!

Related

SQL Scope_Identity is returning 0 or -1

I'm having issues getting the last row affected ID, it's returning 0, this means that it has an error on format being inserted. I executed the stored procedure and added the values manually, it return'd the correct ID. But when I try to do it with the code it keeps returning 0 or -1 ... I tried this last night after several hours and I'm already confused with the values it gave me.
C#:
conn.Open();
cmd.Parameters.AddWithValue("#fileName", fileName);
cmd.Parameters.AddWithValue("#filePrivacy", filePrivacy);
cmd.Parameters.AddWithValue("#filePassword", filePassword);
cmd.Parameters.AddWithValue("#fileDescription", fileDesc);
cmd.Parameters.AddWithValue("#fileOwner", fileOwner);
cmd.Parameters.AddWithValue("#fileDate", DateTime.Now);
cmd.Parameters.AddWithValue("#fileExpire", DateTime.Now.AddMinutes(fileExpire));
cmd.Parameters.AddWithValue("#fileCodeText", fileType);
var fileID = cmd.Parameters.Add("#fileID", SqlDbType.Int);
fileID.Direction = ParameterDirection.Output;
int returnfileID = (int)cmd.ExecuteScalar();
return returnfileID;
Stored Procedure:
CREATE PROCEDURE [dbo].[Upload]
#fileName nvarchar(20),
#filePrivacy int,
#filePassword nvarchar(50),
#fileDescription nvarchar(200),
#fileOwner nvarchar(14),
#fileDate smalldatetime,
#fileExpire smalldatetime,
#fileCodeText int,
#fileID int out
AS
INSERT INTO Files ([FileName], FilePrivacy, FilePassword, FileDescription, FileOwner, FileDate, FileExpire, FileCodeText)
VALUES (#fileName, #filePrivacy, #filePassword, #fileDescription, #fileOwner, #fileDate, #fileExpire, #fileCodeText)
SET #fileID = SCOPE_IDENTITY()
RETURN #fileID
SQL Table:
CREATE TABLE [dbo].[Files] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[FileName] NVARCHAR (20) NOT NULL,
[FilePrivacy] INT NOT NULL,
[FilePassword] NVARCHAR (50) NULL,
[FileDescription] NVARCHAR (200) NULL,
[FileOwner] NVARCHAR (14) NOT NULL,
[FileDate] SMALLDATETIME NOT NULL,
[FileExpire] SMALLDATETIME NOT NULL,
[FileCodeText] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
ExecuteScalar 'Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored'
If you select #fileID (instead of return) it should work.
Alternatively you could access the #fileID parameter value after you execute the query, in which case there's no real point having an ExecuteScalar, you could change it to to ExecutenonQuery.
Use in the SQL
SET #fileID= SCOPE_IDENTITY() RETURN #fileID
SELECT ##IDENTITY;
and in the C# code
int returnfileID = Convert.ToInt32(cmdInsert.ExecuteScalar())
My initial thought is that you are getting back the stored procedure return code. #fileID should be returned by your stored procedure since you have set it as an OUTPUT parameter. Remove the RETURN from your stored procedure. It should pass back the output variable rather than the execution code that way.

SPROC insert with ExecuteNonQuery and ExecuteScalar

SQL insert issue. Running a stored procedure to insert rows to a table and returning the ID created. WHen I run it like this and have an output parameter #ID and use ExecuteNonQuery() it returns -1 for my int idinserted but does give me back the ID inserted. SHouldn't it return 1 since the record was inserted. I'd like to use ExecuteNonQuery to check the record was inserted then grab the inserted ID.
SQL INSERT
#person bigint,
#date datetime,
#ID bigint OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO table(person,DATE_ADDED)
VALUES (#person,#date)
SELECT #ID = SCOPE_IDENTITY()
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#person", person);
cmd.Parameters.AddWithValue("#date", DateTime.Now);
SqlParameter output = new SqlParameter("#ID", SqlDbType.Int);
output.Direction = ParameterDirection.Output;
cmd.Parameters.Add(output);
int idinserted = (int)cmd.ExecuteNonQuery();
if (idinserted > 0)
{
int ID = output.Value;
}
When I do the insert and c# like this with ExecuteScalar()
SQL INSERT
#person bigint,
#date datetime
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO table(person ,DATE_ADDED)
VALUES(#person,#date )
SELECT SCOPE_IDENTITY()
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#person", person);
cmd.Parameters.AddWithValue("#date", DateTime.Now);
long ID = (long)cmd.ExecuteNonScalar();
ExecuteScalar() throws the following error
"Specificed Cast it not valid
Remove
SET NOCOUNT ON;
Because that removes the rowcount!

Returning a scalar from SQL Server to C#

I am trying to return scalar from a database like this:
DbConnection cn = GetConnection2();
cn.Open();
// stored procedure
DbCommand cmd = GetStoredProcCommand(cn, "GetReason");
DbParameter param;
param = CreateInParameter("Reason_Number", DbType.String);
param.Value = number;
cmd.Parameters.Add(param);
param = CreateOutParameter("Result", DbType.String);
param.Direction = ParameterDirection.Output;
cmd.Parameters.Add(param);
cmd.ExecuteScalar();
string reason;
reason = cmd.Parameters["#Result"].Value.ToString();
if (cn.State == ConnectionState.Open)
cn.Close();
return reason;
Here is my stored procedure:
-- =============================================
-- Create date: Today
-- Description: Input Reason # and Return Full Reason Name
-- =============================================
ALTER PROCEDURE [dbo].[GetReason]
#Reason_Number nvarchar(50),
#Result nvarchar(50) output
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT #Result = Field1
FROM dbo.Reasons
WHERE Field1 LIKE #Reason_Number + '%';
END
I am getting an error on the ExecuteScalar line:
System.InvalidOperationException occurred
Message="String[1]: the Size property has an invalid size of 0."
What am I doing wrong?
If you want to use ExecuteScalar, your stored proc needs to return the single row, single column from a SELECT:
ALTER PROCEDURE [dbo].[GetReason]
#Reason_Number nvarchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT Field1
FROM dbo.Reasons
WHERE Field1 LIKE #Reason_Number + '%';
END
and then your code needs to read that value:
var returnedValue = cmd.ExecuteScalar();
and use it from there. Of course, in that case, you also do not need an OUTPUT parameter in your C# code....
Word of warning: that SELECT in your stored proc could potentially return multiple rows. You might want to add a TOP 1 to your select - just to be safe:
SELECT TOP 1 Field1
FROM dbo.Reasons
WHERE Field1 LIKE #Reason_Number + '%';
Just add an other one statement to the end of your stored procedure and remove OUTPUT parameter
SELECT #Result as 'Result'

In C# how to get return value from stored procedure using ExecuteNonQuery

I have the following query:
create proc [dbo].[DeleteParts]
#TransNo nvarchar (6), #fpart nvarchar(25)
AS
DECLARE #Returns BIT
SET #Returns = 1
BEGIN
TRY
BEGIN TRANSACTION
DELETE FROM PARTABLE
WHERE TransNo = #TransNo and fpart = #fpart
COMMIT
END TRY
BEGIN CATCH
Print 'Delete failed'
SET #Returns = 0
-- Any Error Occurred during Transaction. Rollback
IF ##TRANCOUNT > 0
ROLLBACK -- Roll back
END CATCH
RETURN #Returns
This compiles perfectly fine.
In C#, I want to execute this query and get the return value.
My code is as below:
using(System.Data.SqlClient.SqlCommand deletecommand = this._connection.CreateCommand())
{
deletecommand.CommandText = "DeleteParts";
deletecommand.CommandType = System.Data.CommandType.StoredProcedure;
deletecommand.Parameters.AddWithValue("#TransNo", ItemSODBOM.SONO);
deletecommand.Parameters.AddWithValue("#fpart", ItemSODBOM.fbompart);
string ReturnValue = deletecommand.ExecuteNonQuery().ToString();
}
It does not give me any error but instead it is returning number of rows affected, I want to return 1 or 0.
Example: if delete operation success then return 1 and if it fails then return 0.
Any help with source code would be appreciated.
Thanks,
Pradeep
You need a parameter with Direction set to ParameterDirection.ReturnValue
Something like:
SqlParameter returnParameter = deleteCommand.Parameters.Add("RetVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
...
deleteCommand.ExecuteNonQuery();
...
int returnValue = (int) returnParameter.Value;
You Stored Procedure needs to return this return value of course:
create proc [dbo].[DeleteParts]
#TransNo nvarchar (6),
#fpart nvarchar(25)
AS
DECLARE #Returns BIT
SET #Returns = 1
...
RETURN #Returns
I don't see that you are returning the value. Please add the Return statement to return any value from the stored proc.
ExecuteNonQuery will return the number of rows affected but NOT data (that's why its a non-query). So it won't bring anything back.
This might be useful to read:
http://www.dreamincode.net/forums/topic/76434-executenonquery-with-output-parameters/
You'll need to use a different mechanism to get your data out - how about ExecuteReader with an output parameter?
ExecuteNonQuery() returns the ##ROWCOUNT which you cannot set. So really you cannot use it to return values.
Usually the result is returned as a row, like a normal select query would be. You can get at it using a reader or adaptor.
you must specify output type in stored procedures like this
#IDout [int] output
then add this parameter
SPParamReturnCollection sp = new SPParamReturnCollection();
sp.Add(new SPParams { Name = "IDout", ParamDirection = ParameterDirection.Output, Type = SqlDbType.Int });
IF EXISTS(SELECT TransNo FROM [PARTABLE] WHERE TransNo = #TransNo and fpart = #fpart
BEGIN
DELETE FROM PARTABLE
WHERE TransNo = #TransNo and fpart = #fpart
SELECT #TransNo AS RETURNVAL
END
ELSE
BEGIN
SELECT 0 AS RETURNVAL
END
Naming a variable "#Returns" doesn't magically return it's value, you have to actually return the value.
You can't return a bit value, the return value is always an integer. If you want to sent a bit value back, you would have to use an output parameter instead.
Add a return statement to the procedure:
create proc [dbo].[DeleteParts]
#TransNo nvarchar (6), #fpart nvarchar(25)
AS
DECLARE #Returns INT
SET #Returns = 1
BEGIN
TRY
BEGIN TRANSACTION
DELETE FROM PARTABLE
WHERE TransNo = #TransNo and fpart = #fpart
COMMIT
END TRY
BEGIN CATCH
Print 'Delete failed'
SET #Returns = 0
-- Any Error Occurred during Transaction. Rollback
IF ##TRANCOUNT > 0
ROLLBACK
END CATCH
RETURN #Returns
Add a parameter with the direction ReturnValue to receive the return value:
int returnValue;
using(System.Data.SqlClient.SqlCommand deletecommand = this._connection.CreateCommand())
{
deletecommand.CommandText = "DeleteParts";
deletecommand.CommandType = System.Data.CommandType.StoredProcedure;
deletecommand.Parameters.AddWithValue("#TransNo", ItemSODBOM.SONO);
deletecommand.Parameters.AddWithValue("#fpart", ItemSODBOM.fbompart);
var returnParameter = deletecommand.Parameters.Add("#ret", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
deletecommand.ExecuteNonQuery();
returnValue = (int)returnParameter.Value;
}

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