Unable to get data from stored procedure - c#

I'm trying to hit the stored procedure from C# code but always get the result == -1. I don't know where I went wrong. I have searched a lot but didn't' find any solution. Please have a look into my code snippet and guide me what I'm doing wrong.
Thanks in advance.
C# code:
using (SqlConnection connection = new SqlConnection(getConnectionString()))
using (SqlCommand command = new SqlCommand())
{
Int32 rowsAffected;
command.CommandText = "SP_LOGIN_GETUSERBYNAME";
command.CommandType = CommandType.StoredProcedure;
// command.Parameters.Add(new SqlParameter("#Email", userObj.email));
// command.Parameters.Add("#Email", SqlDbType.VarChar).Value = userObj.email.Trim();
command.Parameters.AddWithValue("#Email", userObj.email.ToString());
command.Connection = connection;
connection.Open();
rowsAffected = command.ExecuteNonQuery();
connection.Close();
return rowsAffected;
}
Connection string:
return "Data Source=MUNEEB-PC;Initial Catalog=HRPayRoll;User ID=sa; Password=sa";
Stored procedure code:
CREATE PROCEDURE SP_LOGIN_GETUSERBYNAME
#Email varchar(50)
AS
SELECT *
FROM [User]
WHERE Email = #Email
GO

From ExecuteNonQuery doc;
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
Since your command is SELECT, it is too normal to get -1 as a return value.
If you wanna reach your results, you can use ExecuteReader method instead.
var reader = command.ExecuteReader();
while (reader.Read())
{
// This will iterate your results line by line and
// You can get columns with zero-based values like reader[0], reader[1] or
// can use GetXXX methods of it like GetString(0) or GetInt32(1) etc.
}

Related

Stored Procedure doesn't return records when called from C#, but works in SSMS

I have a stored procedure that correctly returns records when I call it from a SSMS query.
Here is the stored procedure:
CREATE PROCEDURE [dbo].[q_CheckRecords]
#ItemIDS AS VARCHAR(40)
AS
BEGIN
SET NOCOUNT ON
SELECT *
FROM q_Warehouse80_OOS_ItemsNeedingNotification
WHERE item_id = #ItemIDS
END
Calling this from a SSMS query like this:
exec [q_CheckOOSWarehouse80ItemsNeedingNotification] 'B30-R10000-B001'
It correctly returns a row, however when I use this C# code to call the stored procedure, I never get any rows returned.
SqlCommand cmd = null;
SqlDataReader myReader = null;
System.Data.SqlClient.SqlConnection conn = null;
conn = new System.Data.SqlClient.SqlConnection("Data Source=" + sSessionServer + ";database=" + sSessionDatabase + "; Integrated Security=SSPI");
String SQL = "[q_CheckOOSWarehouse80ItemsNeedingNotification]";
cmd = new SqlCommand();
cmd.CommandText = SQL;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Connection = conn;
cmd.Parameters.Add("#ItemIDS", SqlDbType.VarChar).Value = ItemsToBeChecked;
conn.Open();
myReader = cmd.ExecuteReader();
// check to see if any rows were returned.
if (myReader.HasRows)
{
while (myReader.Read())
{
// code to read fields in returned rows here
}
}
conn.Close();
It appears to be a problem with how C# defines the datatype being passed to the stored procedure, but I haven't found any information online on how to solve this problem.
If I were to changed the stored procedure so it's "hard coded"
#ItemIDS AS VARCHAR(40)
AS
BEGIN
SET NOCOUNT ON
select * from q_Warehouse80_OOS_ItemsNeedingNotification where item_id = 'B30-R10000-B001'
END
then the C# call to it correctly indicates that a row was "found".
Any help would be greatly appreciated.
When you don't specify the length of a varChar sql treats it as length 1.
cmd.Parameters.Add("#ItemIDS", SqlDbType.VarChar).Value = ItemsToBeChecked;
Your variable ItemsToBeChecked will be truncated, and I suspect there is nothing matching in your database with just the first character of that value.
Specify the length of the varchar
cmd.Parameters.Add("#ItemIDS", SqlDbType.VarChar, 40).Value = ItemsToBeChecked;
You can verify this is the case by putting a profiler on sql, and executing your c#. You will see the value passed to the #ItemIDS parameter is only 1 character long.
The issue you are facing is because you are not calling your stored procedure in your C# Code.

ExecuteNonQuery returning -1 when using sql COUNT despite the query string

For some reason, ExecuteNonQuery() in C# returns -1, though when I run a query separately, the value returns the actual value needed.
For Example:
try
{
var connString ="Data Source=ServerName;InitialCatalog=DatabaseName;Integrated Security=true;"
SqlConnection conn = new SqlConnection(connString);
SqlCommand someCmd = new SqlCommand("SELECT COUNT(*) FROM SomeTable");
someCmd.Connection = conn;
conn.Open();
var theCount = cmd.ExecuteNonQuery();
conn.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
When the command is executed it returns -1. Though if run the query separately,
SELECT COUNT(*) FROM SomeTable;
Column returns one row with a count of 4 if that table being queried has 4 rows.
Based on MSDN:
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 want to return the number of rows affected by the command and save it to an int variable but since the type of statement is select so it returns -1.
Solution: If you want to get the number of rows affected by the SELECT command and save it to an int variable you can use ExecuteScalar.
var theCount = (int)cmd.ExecuteScalar();
You can use Ef core with Ado.net like this example
var context = new SampleDbContext();
using (var connection = context.Database.GetDbConnection())
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT COUNT(*) FROM SomeTable";
var result = command.ExecuteScalar().ToString();
}
}

Executing Sql Server Stored Procedure and getting OUTPUT INSERTED value

I want to get inserted row key when inserting records.Then I wrote this Sample SQL SP.
CREATE PROCEDURE Temp
AS
BEGIN
SET NOCOUNT ON
insert into Farmer_landDetails
(oth_mas_key,
fmr_key,
anim_typ_key,
anim_count,
land_type_key,
land_availability) OUTPUT INSERTED.oth_det_key values(1,1,1,1,1,1)
END
GO
How to get this OUT value with C# ?
The Output clause of your StoredProcedure returns a single row with a single value.
So the correct method to get its result is through the ExecuteScalar method of an SqlCommand
using(SqlConnection cnn = new SqlConnection(....))
using(SqlCommand cmd = new SqlCommand("Temp", cnn))
{
cnn.Open();
cmd.CommandType = CommandType.StoredProcedure;
int result = Convert.ToInt32(cmd.ExecuteScalar());
}
Notice that I have no idea what datatype is oth_det_key. I assume an integer hence the Convert.ToInt32() on the return value of ExecuteScalar

Get output parameter for ID (primary key)

I have a simple database which has an ID column as primary key, INT, AUTO_INCREMENT and a name column.
I'm trying to insert values into the database and get the ID back. This is part of my code:
using (var connection = new MySqlConnection(...))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText =
"INSERT INTO `adressbook`.`Person` (`ID`, `Name`)
VALUES (#id, #name);";
var idParameter = new MySqlParameter("id", MySqlDbType.Int32);
idParameter.Direction = ParameterDirection.Output;
idParameter.SourceColumn = "ID";
command.Parameters.Add(idParameter);
command.Parameters.AddWithValue("name", "Test");
command.ExecuteNonQuery();
var id = command.Parameters["id"].Value;
connection.Close();
}
However, I always get NULL as the value, even if I can see that the value has been inserted into the database (so the connection settings etc. are fine).
What I have tried
I have read MySQL Connector/NET Output Parameter Returning NULL and Get the value from Output parameter C#, but it still doesn't work if I change my code to
var reader = command.ExecuteReader();
reader.Read();
reader.Close();
I have read the related post Executing MySqlCommand (StoredProcedure) with output parameter, but it didn't help me since I am already using the correct MySql data type.
Just use the LAST_INSERT_ID function of MySql.
using (var connection = new MySqlConnection(...))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = #"INSERT INTO `adressbook`.`Person` (`Name`) VALUES (#name);
SELECT LAST_INSERT_ID();";
command.Parameters.AddWithValue("#name", "Test");
int result = Convert.ToInt32(command.ExecuteScalar());
.......
}
As you can see, you can send multiple commands to MySql with a single execution.
The LAST_INSERT_ID function returns the last autoincrement value.
However, in this scenario, you need to call ExecuteScalar instead of ExecuteNonQuery because the command will return a single row with a single value.
By the way, if you have an Auto_increment column then don't pass anything for that column.

How to check procedure is run and user is exist?

I have procedure like this?
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `check_user`(in username varchar(100), in pass varchar(5000))
BEGIN
select * from users where email=username and password = pass;
END$$
DELIMITER ;
So i call procedure like this.
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "get_user";
cmd.Parameters.AddWithValue("#username", un);
cmd.Parameters.AddWithValue("#pass", Security.Encrypt(pass));
int result = cmd.ExecuteNonQuery();
it shows result as 0. Because not any row affected. In this case can't identify user is exist or not. User exist or not result always 0. So how can i get user is exist or not ?
ExecuteNonQuery should not be used in SELECT statements.
ExecuteNonQuery method is to be used to perform 'Data Manipulation Language'. This is used only in INSERT, DELETE and UPDATE.
ExecuteScalar method will return a single value in the first row, first column from a SELECT statement. So changing your query with SELECT COUNT(*).. can be use.
The ExecuteReader Method will return the result set of a SELECT. This method is to be used when you're querying for a bunch of results, such as rows from a table etc.
Change your query with this:
SELECT COUNT(*) FROM users WHERE email=username AND password = pass;
And use ExecuteScalar() and you are ready to go.
Or you can use DataAdapter Fill like this:
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "get_user";
cmd.Parameters.AddWithValue("#username", un);
cmd.Parameters.AddWithValue("#pass", Security.Encrypt(pass));
DataTable data = new DataTable();
using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
{
da.Fill(data);
}
if (data.Rows.Count > 0)
result = Convert.ToInt32(data.Rows[0][0].ToString());
Read more here.

Categories