Hi all I have the following stored procedure
#UserName varchar(150),
#UserEmail varchar(300),
#UserPassword varchar(150),
#ContactNumber varchar(150),
#ContactMobile varchar(150),
#AreaOfCountry varchar(150),
#UserId int OUTPUT,
#AllreadyReg int OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--DECLARE #UserId int, #AllreadyReg int
IF (SELECT COUNT(UserId) FROM Users WHERE (UserName = #UserName) OR (UserEmail = #UserEmail)) > 0
BEGIN
SET #UserId = 0
SET #AllreadyReg = 1
END
ELSE
BEGIN
INSERT INTO Users (UserName,UserEmail,UserPassword,ContactNumber,ContactMobile,AreaOfCountry) VALUES (#UserName,#UserEmail,#UserPassword,#ContactNumber,#ContactMobile,#AreaOfCountry)
SELECT #UserId = SCOPE_IDENTITY()
SET #AllreadyReg = 0
END
however when I use it using c# and asp.net its not returning anything, however when I just execute it it does have a results #UserId and #AllreadyReg but the return value is 0 and a single field.
my c# code is below but it never has any rows
using (SqlConnection con = new SqlConnection(connectionString))
{
Response.Write("Line 61");
using (SqlCommand cmd = new SqlCommand("spR_Register", con))
{
Response.Write("line 64");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#UserName", TxtUsername.Text.Trim());
cmd.Parameters.AddWithValue("#UserEmail", TxtEmail.Text.Trim());
cmd.Parameters.AddWithValue("#UserPassword", TxtPassword.Text.Trim());
cmd.Parameters.AddWithValue("#ContactNumber", TxtPhone.Text);
cmd.Parameters.AddWithValue("#ContactMobile", TxtMobile.Text);
cmd.Parameters.AddWithValue("#AreaOfCountry", TxtAreaOfCountry.SelectedValue);
cmd.Parameters.AddWithValue("#UserId", ParameterDirection.Output);
cmd.Parameters.AddWithValue("#AllreadyReg", ParameterDirection.Output);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
Response.Write("line 78");
etc etc
can anyone help
thanks
With the edit: the mistake is using ExecuteReader on a command that doesn't select a data grid - that should be done with ExecuteNonQuery.
The important thing here is how the parameter is added. For example:
var alreadyReg = cmd.CreateParameter();
alreadyReg.Direction = System.Data.ParameterDirection.Output;
alreadyReg.ParameterName = "AllreadyReg";
alreadyReg.DbType = DbType.Int32;
cmd.Parameters.Add(alreadyReg);
//...
cmd.ExecuteNonQuery();
//...
int val = (int)alreadyReg.Value;
Depending on the type of DbCommand object, there may be an overload that accepts all of these in one line - the above assumes just DbCommand. With SqlCommand, you can simplify a bit:
var alreadyReg = cmd.Parameters.Add("AllreadyReg", SqlDbType.Int);
alreadyReg.Direction = ParameterDirection.Output;
//...
cmd.ExecuteNonQuery();
//...
int val = (int)alreadyReg.Value
You might have already handled it, but just in case, make sure to specify direction of parameter in c# code.
Here
cmd.Parameters.AddWithValue("#UserId", ParameterDirection.Output);
wrong usage of AddWithValue. The second parameter is parsed as parameter value, not direction type. Use proper parameter contructor and the add the result to collection.
Related
The Stored Procedure:
BEGIN
SELECT * FROM `user` WHERE `EmailAddress`= #p0 AND `Password` = #p1;
END
Where #p0 and #p1 are Varchar(100).
And the code:
using (MySqlConnection con = new MySqlConnection(Database.MySQLConstring))
{
using (MySqlCommand cmd = new MySqlCommand("LoginCheck", con))
{
cmd.CommandType = CommandType.StoredProcedure; //"LoginCheck"
cmd.Parameters.AddWithValue("email", Email);
cmd.Parameters.AddWithValue("password", Pword);
con.Open();
MySqlDataReader reader = cmd.ExecuteReader();
UserModel UM = new UserModel();
While (reader.Read())
{
UM.UserId = (int)reader["UserID"];
UM.DisplayName = (string)reader["DisplayName"];
UM.Moderator = (int)reader["Moderator"];
}
con.Close();
While(!string.IsNullOrEmpty(UM.DisplayName) && UM.UserId != 0)
{
Result = 1;
return UM;
}
Result = -1;
return UM;
}
}
The code runs succesfull until it comes to the while(reader.Read()) part, then it skips it and goes to the con.close(). No errors or exceptions are thrown. It worked when I was using it when everything was SQL and not MySQL ,but I need to get it working in MySQL.
When I run the stored Procedure itself in de databse then I get my result that I need. but when I use the code it will skip the While part of the code.
If I were going to execute a procedure that was declared as:
CREATE PROCEDURE x(em VARCHAR, pw VARCHAR) --declaration of parameters
BEGIN
SELECT * FROM `user` WHERE `EmailAddress`= em AND `Password` = pw;
END
I would ensure the parameters in my C# code were named the same as in the declaration of the stored procedure:
cmd.Parameters.Add(new MySqlParameter("em", Email));
cmd.Parameters.Add(new MySqlParameter("pw", Password));
I suspect that your query is not getting any rows, because the values you set never make it into the parameters, and are hence never used to query. reader.Read() returns false, because there are no rows. Also make sure that the values for EMail and Password that you're querying really do exist in the table
Try as a debugging thing, to make your query like:
SELECT UserID, DisplayName, Moderator FROM `user` WHERE `EmailAddress`= #p0 AND `Password` = #p1
UNION ALL
SELECT 0, CONCAT_WS(' ', 'There is no user with email/password of', #p0, '/', #p1), '' FROM DUAL;
Or however your parameters are named now..
Your reader.Read()should now return true because this query should always return a row, so inspect the value of DisplayName, it should tell what search terms were applied
I read a lot about SQL injections lately and I know a SqlParameter will not prevent injections for sure, but is a table parameter as safe as a single parameter?
Some untested uncompiled example code for clarification:
Is this...
SQL:
CREATE PROCEDURE dbo.InsertSingle
#Name nvarchar(max),
#Phone nvarchar(max)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO FooBar.dbo.SomeTable
VALUES(#Name, #Phone)
END
GO
C#:
foreach(User u in Users)
{
Connection.Open();
SqlCommand com = Connection.CreateCommand();
com.CommandType = CommandType.StoredProcedure;
com.CommandText = "dbo.InsertSingle";
SqlParameter p = new SqlParameter("#Name", u.Name);
com.Parameters.Add(p);
p = new SqlParameter("#Phone", u.Phone);
com.Parameters.Add(p);
com.ExecuteScalar();
}
as safe as this?
SQL:
CREATE PROCEDURE dbo.InsertBunch
#ValuesAsTable dbo.ValuesAsTableType READONLY
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO FooBar.dbo.SomeTable
SELECT *
FROM #ValuesAsTable
END
GO
C#:
DataTable valuesAsTable = Users.GetSomeInsertData();
Connection.Open();
SqlCommand com = Connection.CreateCommand();
com.CommandType = CommandType.StoredProcedure;
com.CommandText = "dbo.InsertBunch";
SqlParameter p = new SqlParameter("#valuesAsTable", valuesAdTable);
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "dbo.ValuesAsTableType";
com.Parameters.Add(p);
com.ExecuteScalar();
I really tried to search it, but I cannot find good input. Can anyone link me in the right direction?
Thanks in advance
Typed parameters will prevent SQL injection if there is no possibility that they get interpreted as literal commands, and executed. Whether they are transported as scalar or table-valued parameters, does not make any difference in this regard.
I have a table called 'MatchType' and it contains:
ID | MatchTypeName
1 | One Day
2 | Two Day
3 | T20
I have a method to retrieve a record from that table based on a sting that will match a value in MatchTypeName:
public static int GetByName(string matchType)
{
MatchType item = new MatchType();
using (SqlConnection con = new SqlConnection(BaseDataAccessLayer.GetConnectionStringByName()))
{
using (SqlCommand cmd = new SqlCommand(STORED_PROC_GetByName, con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#matchTypeName", SqlDbType.VarChar, 20).Value = matchType;
con.Open();
using (IDataReader reader = cmd.ExecuteReader())
{
item.LoadFromReader(reader);
}
}
}
return item.Id;
}
This method calls this stored procedure:
CREATE PROCEDURE [dbo].[MatchType_GetByName]
(#matchTypeName varchar(20))
AS
BEGIN
SET NOCOUNT ON
SELECT
[Id], [MatchTypeName]
FROM
[dbo].[MatchType]
WHERE
[MatchTypeName] = #matchTypeName
RETURN ##ERROR
END
When calling the GetByName method I am passing in a string "One Day". I have confirmed this through debugging. I can't post an error message that is helpful as there isn't one being generated. Just no data is being returned in the reader...
I have a couple of other methods and stored procedures that use a similar process and they work. The only thing that I can see is the difference is that I am using the WHERE clause on a varchar/string value which is something that the other queries don't do...
Yet i can run this stored proc and it returns all the records..
BEGIN
SET NOCOUNT ON
SELECT
[Id],
[MatchTypeName]
FROM
[dbo].[MatchType]
RETURN ##ERROR
END
The default length for varchar declared without size is 1. You declared it like that in your stored proc parameter so you're only passing the first character.
Change your declaration:
(#matchTypeName varchar)
to a relevant size:
(#matchTypeName varchar(20))
Also, add the size in the code and make sure that the case in your parameter name matches your stored proc:
cmd.Parameters.Add("#matchTypeName", SqlDbType.VarChar, 20).Value = matchType;
The procedure is running the query and showing the results (which is why it works in SSMS), but doesn't actually return anything. Try this (note, I haven't actually tested it).
CREATE PROCEDURE [dbo].[MatchType_GetByName]
#matchTypeName varchar(20),
#matchTypeID INT OUTPUT
AS
BEGIN
SET NOCOUNT ON
SELECT
#matchTypeID = [Id], [MatchTypeName]
FROM
[dbo].[MatchType]
WHERE
[MatchTypeName] = #matchTypeName
RETURN ##ERROR
END
Try this:
using (SqlCommand cmd = new SqlCommand(STORED_PROC_GetByName, con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#matchTypeName", matchType);
con.Open();
using (IDataReader reader = cmd.ExecuteReader())
{
item.LoadFromReader(reader);
}
}
SqlCommand.Parameters Property
As a part of getting to learn Stored procedures , I came up with this.
CREATE PROCEDURE StoredProcedure1
#oResult int output
AS
BEGIN
SELECT #oResult = 2
RETURN #oResult
END
But the problem is on execution of this SP, it just returns something like.
Procedure or function 'StoredProcedure1' expects parameter '#oResult', which was not supplied.
I want this procedure just to return a result when called.
Any ideas why ?
I supplied as it was asking,EXEC StoredProcedure1 #oResult = 0 but it just says Command Completed Successfully but no output.
Any ideas why ?
In ADO.NET when you call a Stored Procedure that expects a parameter, you need to give that parameter, also if it is an output parameter.
using(SqlConnection cnn = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand("StoredProcedure1", cnn))
{
cnn.Open();
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p = new SqlParameter("#oResult", SqlDbType.Int);
p.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
int result = Convert.ToInt32(cmd.Parameters["#oResult"].Value);
}
Of course, in the stored procedure you should set the #oResult parameter in some way as explained in the other answers, but if you use an OUTPUT parameter there is no need to RETURN the same value.
However you could have both an OUTPUT parameter and a RETURN value if you need to. In this case your call from C# should be
using(SqlConnection cnn = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand("StoredProcedure1", cnn))
{
cnn.Open();
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p = new SqlParameter("#oResult", SqlDbType.Int);
p.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p);
// Here the name #returnValue is arbitrary, you could call it whatever you like
SqlParameter r = new SqlParameter("#returnValue", SqlDbType.Int);
r.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(r);
cmd.ExecuteNonQuery();
int result = Convert.ToInt32(cmd.Parameters["#oResult"].Value);
int returnValue = Convert.ToInt32(cmd.Parameters["#returnValue"].Value);
}
But keep in mind that RETURN values are limited to Integer Expressions.
You could do this:
Store procedure
CREATE PROCEDURE StoredProcedure1
#oResult int output
AS
BEGIN
SET #oResult = 2
END
And then calling it like this:
DECLARE #Result INT
exec StoredProcedure1 #oResult = #Result output
SELECT #Result
This will output
2
Update:
Like addressed in the comment. You could also simplify the statement. By doing this:
DECLARE #Result INT
exec StoredProcedure1 #Result output
SELECT #Result
Reference:
Execute stored procedure with an Output parameter?
You do not need to write return ..try below code :-
CREATE PROCEDURE StoredProcedure1
#oResult int output
AS
BEGIN
SET #oResult = 2
END
CREATE PROCEDURE SP1
(
#oResult int output
)
AS
BEGIN
SET #oResult=2
Select #oResult
END
I am using the following code to run a stored procedure given some input from user. The stored procedure updates some tables if the input was valid and there isn’t going to be a duplicate record.
If the input is invalid or that record already exists, stored procedure returns a value of the OUT parameter that is assigned to variable message.
How can I display the value of message on the screen? Messabebox would be ideal, but couldn’t find where should call it from.
partial void MyStorProc_Inserting(MyStorProcOperation entity)
{
using (SqlConnection connection = new SqlConnection())
{
string connMyDB = this.DataWorkspace.MyDB.Details.Name;
connection.ConnectionString = ConfigurationManager.ConnectionStrings[connMyDB].ConnectionString;
string proc = "[MyDB].[dbo].[szMyStorProc]";
using (SqlCommand command = new SqlCommand(proc, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#Uname", entity.Uname));
command.Parameters.Add(new SqlParameter("#BU", entity.BU));
SqlParameter output = new SqlParameter();
output.ParameterName = "#ResultDescription";
output.SqlDbType = System.Data.SqlDbType.VarChar;
output.Direction = ParameterDirection.Output;
output.Size = 256;
command.Parameters.Add(output);
connection.Open();
command.ExecuteNonQuery();
string message = output.Value.ToString();
}
}
this.Details.DiscardChanges();
}
stored procedure goes somewhat like this:
CREATE PROCEDURE [dbo].[szMyStorProc]
-- Add the parameters for the stored procedure here
#Uname varchar(50) = '',
#BU varchar(50) = '',
#ResultDescription varchar(256)= '' OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #EmployeeID INT
DECLARE #BUID INT
SELECT #EmployeeID = ID FROM tEmployee WHERE Uname = #Uname
IF #EmployeeID IS NULL
BEGIN
SELECT #ResultDescription = 'User name not found'
PRINT #ResultDescription
END
ELSE
...
...
END
GO