I want to make a method that execute a stored procedure whose name is a parameter of the method, and the parameters (variables) of the stored procedure are provided by SqlParameter[] param as follows:
public void modifying(string method, SqlParameter[] param)
{
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-HP5H4JL\SQLEXPRESS;Initial Catalog=Pocket Money;Integrated Security=True;Pooling=False");
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = method;
cmd.Connection = con;
if (param != null)
cmd.Parameters.AddRange(param);
cmd.ExecuteNonQuery();
}
This method is in the class Modify. Now I want to execute the stored procedure insertItemStudents:
CREATE PROCEDURE insertItemStudents
#name VARCHAR(50),
#class VARCHAR(10),
#Gender BIT,
#BirthDate DATE,
#PhoneNumber CHAR(11),
#Email VARCHAR(50)
AS
INSERT INTO Students( StudentName, Class, Gender, BirthDate, PhoneNumber, Email)
VALUES (#name, #class, #Gender, #BirthDate, #PhoneNumber, #Email)
RETURN 0
I created a form in which there are text boxes to insert the new values. But the problem is: how to pass the SqlParameter[] as an argument?
You can try this.
SqlParameter[] paramCollection = new SqlParameter[1];
SqlParameter param1 = new SqlParameter("name", typeof(string));
paramCollection[0] = param1;
modifying("methodname", paramCollection);
Related
I am facing this error from my C# code. Executing the stored procedure in SQL Server is no problem.
Procedure or function 'SP' expects parameter '#outputparam', which was not supplied.
public string function1(int param1, string param2)
{
SqlDataAdapter sqladapter = new SqlDataAdapter();
SqlConnection conn = new SqlConnection(strcon);
SqlCommand cmd;
cmd = new SqlCommand("SP", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#param1", param1);
cmd.Parameters.AddWithValue("#param2", param2);
SqlParameter returnParameter = cmd.Parameters.Add("#outputparam", SqlDbType.NVarChar);
returnParameter.Direction = ParameterDirection.ReturnValue;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
return cmd.Parameters["#outputparam"].Value.ToString();
}
CREATE PROCEDURE [dbo].[SP]
(#param1 int,
#param2 nvarchar(50),
#outputparam nvarchar(20) OUTPUT)
Try these code
SqlParameter returnParameter = cmd.Parameters.Add("#outputparam", DbType.String);
returnParameter.Direction = ParameterDirection.ReturnValue;
change to
cmd.Parameters.Add("#outputparam", DbType.String, ParameterDirection.Output);
and
return cmd.Get<string>("#outputparam");
I am using a GridView, and I followed instructions here: http://www.aspsnippets.com/Articles/GridView-CRUD-Select-Insert-Edit-Update-Delete-using-Single-Stored-Procedure-in-ASPNet.aspx
Now I am getting the error: Procedure or function 'spRegistrantsGridView' expects parameter '#RegistrantId', which was not supplied
This is my StoredProcedure:
ALTER PROCEDURE [dbo].[spRegistrantsGridView]
#Action nvarchar(10),
#RegistrantId int,
#FirstName nvarchar(20),
#LastName nvarchar(25),
#AddressLine1 nvarchar(50),
#AddressLine2 nvarchar(50),
#City nvarchar(30),
#State nvarchar(2),
#Zip nvarchar(10),
#Country nvarchar(20),
#Phone nvarchar(15),
#PhoneExt nvarchar(4),
#Email nvarchar(50),
#MemberId bigint,
#Comments nvarchar(300)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
--SELECT
IF #Action = 'SELECT'
BEGIN
SELECT RegistrantId,
FirstName,
LastName,
AddressLine1,
AddressLine2,
City,
State,
Zip,
Country,
Phone,
PhoneExt,
Email,
Comments
FROM Registrant
END
--INSERT
IF #Action = 'INSERT'
BEGIN
INSERT INTO Registrant(
FirstName,
LastName,
AddressLine1,
AddressLine2,
City,
State,
Zip,
Country,
Phone,
PhoneExt,
Email,
MemberId,
Comments)
VALUES (
#FirstName,
#LastName,
#AddressLine1,
#AddressLine2,
#City,
#State,
#Zip,
#Country,
#Phone,
#PhoneExt,
#Email,
#MemberId,
#Comments)
END
--UPDATE
IF #Action = 'UPDATE'
BEGIN
UPDATE Registrant SET
FirstName = #FirstName,
LastName = #LastName,
AddressLine1 = #AddressLine1,
AddressLine2 = #AddressLine2,
City = #City,
State = #State,
Zip = #Zip,
Country = #Country,
Phone = #Phone,
PhoneExt = #PhoneExt,
Email = #Email,
MemberId = #MemberId,
Comments = #Comments
WHERE RegistrantId = #RegistrantId
END
--DELETE
IF #Action = 'DELETE'
BEGIN
DELETE FROM Registrant
WHERE RegistrantId = #RegistrantId
END
END
And the part of my C# where it throws the error (specifically at sda.Fill(dt);):
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.BindGrid();
}
}
private void BindGrid()
{
string constr = ConfigurationManager.ConnectionStrings["Events2"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand("spRegistrantsGridView"))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Action", "SELECT");
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
}
}
}
The parameter #RegistrantId wasn't added when calling the stored procedure.
Add the parameter to your code like so:
private void BindGrid()
{
string constr = ConfigurationManager.ConnectionStrings["Events2"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand("spRegistrantsGridView"))
{
cmd.CommandType = CommandType.StoredProcedure;
// missing parameter
cmd.Parameters.AddWithValue("#RegistrantId", [insert id]);
cmd.Parameters.AddWithValue("#Action", "SELECT");
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
}
}
}
EDIT
Now your SP is in your question the issue is you have multiple parameters specified but you're only adding one in your c# code. Either remove the params from your SP or make them optional by adding = null
e.g.
ALTER PROCEDURE [dbo].[spRegistrantsGridView]
#Action nvarchar(10),
#RegistrantId int = null,
#FirstName nvarchar(20) = null,
...
i have a stored procedure
ALTER PROC TESTLOGIN
#UserName varchar(50),
#password varchar(50)
As
Begin
declare #return int;
set #return = (SELECT COUNT(*)
FROM CPUser
WHERE UserName = #UserName
AND Password = #password);
return #return;
End
and in c#
SqlConnection con = db.con;
SqlCommand cmd = new SqlCommand("TESTLOGIN", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter parm = new SqlParameter("#return", SqlDbType.Int);
parm.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(parm);
cmd.Parameters.Add(new SqlParameter("#UserName", txtUserName.Text.ToString().Trim()));
cmd.Parameters.Add(new SqlParameter("#password", txtPassword.Text.ToString().Trim()));
cmd.ExecuteNonQuery();
con.Close();
int id = Convert.ToInt32(parm.Value);
but it always return 0. Please help me to solve this problem
You need a parameter with Direction set to ParameterDirection.ReturnValue in code but no need to add an extra parameter in SP. Try this
SqlParameter returnParameter = cmd.Parameters.Add("RetVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
cmd.ExecuteNonQuery();
int id = (int) returnParameter.Value;
2 things.
The query has to complete on sql server before the return value is sent.
The results have to be captured and then finish executing before
the return value gets to the object.
In English, finish the work and then retrieve the value.
this will not work:
cmm.ExecuteReader();
int i = (int) cmm.Parameters["#RETURN_VALUE"].Value;
This will work:
SqlDataReader reader = cmm.ExecuteReader();
reader.Close();
foreach (SqlParameter prm in cmd.Parameters)
{
Debug.WriteLine("");
Debug.WriteLine("Name " + prm.ParameterName);
Debug.WriteLine("Type " + prm.SqlDbType.ToString());
Debug.WriteLine("Size " + prm.Size.ToString());
Debug.WriteLine("Direction " + prm.Direction.ToString());
Debug.WriteLine("Value " + prm.Value);
}
if you are not sure
check the value of the parameter
before during and after the results have been processed by the reader.
you can try this.Add the parameter as output direction and after executing the query get the output parameter value.
SqlParameter parmOUT = new SqlParameter("#return", SqlDbType.Int);
parmOUT.Direction = ParameterDirection.Output;
cmd.Parameters.Add(parmOUT);
cmd.ExecuteNonQuery();
int returnVALUE = (int)cmd.Parameters["#return"].Value;
Procedure never returns a value.You have to use a output parameter in store procedure.
ALTER PROC TESTLOGIN
#UserName varchar(50),
#password varchar(50)
#retvalue int output
as
Begin
declare #return int
set #return = (Select COUNT(*)
FROM CPUser
WHERE UserName = #UserName AND Password = #password)
set #retvalue=#return
End
Then you have to add a sqlparameter from c# whose parameter direction is out.
Hope this make sense.
If you want to to know how to return a value from stored procedure to Visual Basic.NET. Please read this tutorial: How to return a value from stored procedure
I used the following stored procedure to return the value.
CREATE PROCEDURE usp_get_count
AS
BEGIN
DECLARE #VALUE int;
SET #VALUE=(SELECT COUNT(*) FROM tblCar);
RETURN #VALUE;
END
GO
Do it this way (make necessary changes in code)..
SqlConnection con = new SqlConnection(GetConnectionString());
con.Open();
SqlCommand cmd = new SqlCommand("CheckUser", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p1 = new SqlParameter("username", username.Text);
SqlParameter p2 = new SqlParameter("password", password.Text);
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
SqlDataReader rd = cmd.ExecuteReader();
if(rd.HasRows)
{
//do the things
}
else
{
lblinfo.Text = "abc";
}
I want to execute a .sql script from C#. Basically the script inserts a row into few different tables.
The point is I have values in C# code that I need to pass to the .sql query. These values will be collected during program execution.
Here is the query that I want to execute from C# code:
INSERT INTO [DB].[dbo].[User]
([Id]
,[AccountId]
,[FirstName]
,[LastName]
,[JobTitle]
,[PhoneNumber]
)
VALUES
('00A640BD-1A0D-499D-9155-BA2B626D7B68'
,'DCBA241B-2B06-48D7-9AC1-6E277FBB1C2A'
,'Mark'
,'Wahlberg'
,'Actor'
,'9889898989'])
GO
The values will vary from time to time i.e., they are captured in C# code and need to be passed.
Can anyone please help me do this..I am learning both C# and SQL. Thanks a lot.
You could open yourself up to SQL injection attacks here, so best practice is to use parameters:
using (SqlConnection dbConn = new SqlConnection(connectionString))
{
dbConn.Open();
using (SqlTransaction dbTrans = dbConn.BeginTransaction())
{
try
{
using (SqlCommand dbCommand = new SqlCommand("insert into [DB].[dbo].[User] ( [Id], [AccountId], [FirstName], [LastName], [JobTitle], [PhoneNumber] ) values ( #id, #accountid, #firstname, #lastname, #jobtitle, #phonenumber );", dbConn))
{
dbCommand.Transaction = dbTrans;
dbCommand.Parameters.Add("id", SqlType.VarChar).Value = id;
dbCommand.Parameters.Add("accountid", SqlType.VarChar).Value = accountId;
dbCommand.Parameters.Add("firstname", SqlType.VarChar).Value = firstName;
dbCommand.Parameters.Add("lastname", SqlType.VarChar).Value = lastName;
dbCommand.Parameters.Add("jobtitle", SqlType.VarChar).Value = jobTitle;
dbCommand.Parameters.Add("phonenumber", SqlType.VarChar).Value = phoneNumber;
dbCommand.ExecuteNonQuery();
}
dbTrans.Commit();
}
catch (SqlException)
{
dbTrans.Rollback();
throw; // bubble up the exception and preserve the stack trace
}
}
dbConn.Close();
}
This is a good article for beginners with ADO.Net
EDIT - Just as a bit of extra info, I've added a transaction to it so if the SQL command fails it will rollback.
using SqlCommand cmd= conn.CreateCommand())
{
cmd.CommandText = #"INSERT INTO TABLE (COLUMNS) VALUES (#Id, #account etc...
cmdUser.Parameters.Add(new SqlParameter("#User", SqlDbType.UniqueIdentifier) { Value = UserTypeID });
cmdUser.Parameters.Add(new SqlParameter("#Id", SqlDbType.UniqueIdentifier) { Value = ApprovalTypeID });
cmdUser.Parameters.Add(new SqlParameter("#AccountId", SqlDbType.UniqueIdentifier) { Value = UserID });
cmdUser.Parameters.Add(new SqlParameter("#FirstName", SqlDbType.NVarChar, 100) { Value = Name });
cmdUser.Parameters.Add(new SqlParameter("#JobTitle", SqlDbType.NVarChar, 100) { Value = Surname });
cmdUser.Parameters.Add(new SqlParameter("#PhoneNumber", SqlDbType.Bit) { Value = Active });
cmdUser.ExecuteNonQuery();
}
try
{
using (SqlConnection cn = new SqlConnection(this.ConnectionString))
{
SqlCommand cmd = new SqlCommand("Insert_User", cn);
cmd.CommandType = CommandType.StoredProcedure;
if (cn.State != ConnectionState.Open)
cn.Open();
cmd.Parameters.Add("Id", SqlDbType.NVarChar).Value = "00A640BD-1A0D-499D-9155-BA2B626D7B68";
cmd.Parameters.Add("AccountId", SqlDbType.NVarChar).Value = "DCBA241B-2B06-48D7-9AC1-6E277FBB1C2A";
cmd.Parameters.Add("FirstName", SqlDbType.NVarChar).Value = "Mark";
cmd.Parameters.Add("LastName", SqlDbType.NVarChar).Value = "Wahlberg";
cmd.Parameters.Add("JobTitle", SqlDbType.NVarChar).Value = "Actor";
cmd.Parameters.Add("PhoneNumber", SqlDbType.NVarChar).Value = "9889898989";
return cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
and for stored procedure, in sql:
create procedure [Insert_User]
(
#id as nvarchar(100),
#accid as nvarchar(100),
#fname as nvarchar(100),
#lname as nvarchar(100),
#jobtitle as nvarchar(100),
#phone as nvarchar(100)
)
INSERT INTO [DB].[dbo].[User]
([Id]
,[AccountId]
,[FirstName]
,[LastName]
,[JobTitle]
,[PhoneNumber]
)
VALUES
(#id
,#accid
,#fname
,#lname
,#jobtitle
,#phone])
also, you can use text boxes or other input type controls to set values. You can change dataType, as you wish, such as uniqueidentifier, int, etc. If one or more of values are set as identifire, eg. AccountID, remove them from query.
Frankly, ADO.NET makes it hard to do things like this correctly. Tools like Dapper exist to make that easier:
dbConn.Execute(
#"insert into [DB].[dbo].[User] ( [Id], [AccountId], [FirstName], [LastName],
[JobTitle], [PhoneNumber] )
values ( #id, #accountId, #firstName, #lastName, #jobTitle, #phoneNumber )",
new { id, accountId, firstName, lastName, jobTitle, phoneNumber });
This will deal with all the parameterization for you, efficiently, effectively, and safely.
There are similar APIs for executing queries and populating objects.
The above answers definitely good solutions for the question. However, I would like to recommend more dynamic and robust solution.
Here is your controller (in my example Ajax call)
public JsonResult RecordThis(FormCollection fc)
{
SqlRecord.RecordThis(fc);
return View();
}
Then, on your Model (in example SqlRecord) create "Record" function;
public static void Record(FormCollection fc)
{
var sql = "INSERT INTO RecordTable VALUES ('#Email','#Name','GETDATE()')";
var parameters = BuildSqlParams(fc);
ExecuteInlineSqlWithParams(sql, yourconnectionstringhere, parameters);
}
Then, add these two functions below to be used for any function like "Record". You can add conditions as well such as excluding tokens.
public static List<SqlParameter> BuildSqlParams(FormCollection fc)
{
var parameters = new List<SqlParameter>();
foreach(var key in fc.AllKeys)
{
if(key != "__RequestVerificationToken")
parameters.Add(new SqlParameter("#"+key+"", fc[key]));
}
return parameters;
}
public static void ExecuteInlineSqlWithParams(string sql, string cnn, List<SqlParameter> parameters )
{
var connection = new SqlConnection(cnn);
var command = new SqlCommand(sql, connection);
command.CommandType = CommandType.Text;
foreach(var param in parameters)
{
command.Parameters.Add(param);
}
using (connection)
{
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
You'll need the System.Data.SqlCommand class.
Change the fixed values to named parameters. For example:
INSERT INTO [TABLE] (Column1) values (#Value1) // the #Value1 is the named parameter
Example:
var connection = new SqlConnection("connectionstring");
var command = connection.CreateCommand();
command.CommandText = "insert...."; // sql command with named parameters
// set the named parameter values
command.Parameters["#Value1"] = "Mark wa...";
// execute
command.ExecuteNonQuery();
SqlCommand reference:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
returning int value from stored procedure and check it in asp.net code to validate login form
hello all please i need help in this code as it is stored procedure validate username and password , the problem here is that form validate any data even it doesn't stored in database and i tried to fix code many times but really i haven't any more thing to do in it , any one can help me to solve this problem
this is stored procedure
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[login_procedure] #username Varchar =50, #password varchar=50, #result int OUTPUT
as
Declare #user_name varchar , #pass_word varchar
Set #user_name = #username
Set #pass_word = #password
if EXISTS (select #username , #password from data where username= #user_name and password=#pass_word)
select #result=1
else
select #result=0
and this is asp.net code
SqlConnection conn = new SqlConnection ("Data Source=ANAGUIB-LAPNEW\\SQLEXPRESS;Initial Catalog=account;Integrated Security=True");
SqlCommand cmd = new SqlCommand("login_procedure", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter paramReturnValue = new SqlParameter();
paramReturnValue.ParameterName = "#result";
paramReturnValue.SqlDbType = SqlDbType.Int;
cmd.Parameters.Add(paramReturnValue);
cmd.Parameters["#result"].Direction = ParameterDirection.Output;
conn.Open();
cmd.Parameters.AddWithValue("#username", TextBox1.Text);
cmd.Parameters.AddWithValue("#password", TextBox2.Text);
int resultID = Convert.ToInt32(cmd.ExecuteScalar());
if (Convert.ToInt32(resultID) == 0)
{
Response.Redirect("hello.aspx");
}
else
{
Response.Write("error");
}
conn.Close();
}
Your stored-procedure has OUTPUT parameter and it is good practice to access value of output parameter after closing the connection.
I've changed proc.
ALTER PROCEDURE login_procedure
#username Varchar(50),
#password varchar(50),
#result int OUTPUT
AS
IF EXISTS (select username from data where username= #username and password=#password)
set #result=1
else
set #result=0
Demo: How to pass parameters (IN and OUT)?
SqlConnection cn = new SqlConnection(cnstr);
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandText = "login_procedure";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter param1 = new SqlParameter("#username", System.Data.SqlDbType.VarChar, 50);
SqlParameter param2 = new SqlParameter("#password", System.Data.SqlDbType.VarChar, 50);
SqlParameter resultParam= new SqlParameter("#result", System.Data.SqlDbType.Int);
resultParam.Direction = System.Data.ParameterDirection.Output;
param1.Value = TextBox1.Text;
param2.Value = TextBox2.Text;
cmd.Parameters.Add(param1);
cmd.Parameters.Add(param2);
cmd.Parameters.Add(resultParam);
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
int retVal;
int.TryParse(resultParam.Value.ToString(),out retVal);
if(retVal==1)
//
else
//
In this code
if EXISTS (select #username ,
#password
from data
where username= #user_name and password=#pass_word)
select #result=1
else
select #result=0
You are returning 1 if the given input is validated in your C# code you are giving error when the return value is not 0, that is why every input even which does not exist in your table is validated.Try this;
if (resultID == 1)
{
Response.Redirect("hello.aspx");
}
else
{
Response.Write("error");
}
And you do not have to Convert the return value of stored procedure twice, once is enough.