Calling a stored procedure with a parameter that is a table - c#

I'm trying to call the below stored procedure but I am unsure on what to pass through one of the parameters (#UnsubscribeTypes) I've tried passing in a list but got a compile error. I'm using c#, Visual Studio 2010, web forms. Any ideas on what I should pass in when calling the stored procedure in my c# code (ado.net)?
Here is my stored procedure:
ALTER PROCEDURE [czone].[SetAccountEmailPreference]
(
#EmailAddress VARCHAR(255),
#UnsubscribeTypes dbo.ListOfIDs READONLY,
#SentEmailID INT = NULL
)
AS
SET NOCOUNT ON;
EXEC dbo.LogObjectExecution ##PROCID;
DECLARE #UnsubscribeID INT = (SELECT TOP 1 UnsubscribeID
FROM Email.dbo.Unsubscribe
WHERE EmailAddress = #EmailAddress
ORDER BY UnsubscribeID DESC);
-- Unsubscribe
IF ((SELECT COUNT(*) FROM #UnsubscribeTypes) > 0)
BEGIN
IF(#UnsubscribeID IS NULL)
BEGIN
-- ADD UNSUBSCRIBE
INSERT INTO Email.dbo.Unsubscribe (EmailAddress, CreatedDate)
VALUES (#EmailAddress, CURRENT_TIMESTAMP)
SET #UnsubscribeID = ##IDENTITY;
END
-- Remove current mappings
DELETE FROM Email.dbo.UnsubscribeTypeMapping
WHERE UnsubscribeFK = #UnsubscribeID;
-- Add new mappings
INSERT INTO Email.dbo.UnsubscribeTypeMapping (UnsubscribeFK, UnsubscribeTypeFK, SentEmailFK)
SELECT
#UnsubscribeID, ID, #SentEmailID
FROM
#UnsubscribeTypes;
END
-- Subscribe
ELSE IF (#UnsubscribeID IS NOT NULL)
BEGIN
DELETE FROM Email.dbo.Unsubscribe
WHERE UnsubscribeID = #UnsubscribeID;
END

dbo.ListOfIDs is a table type. First, find out the type in your database, then check columns. generate a datatable with rows containing the UnsubscribeTypeFK ids.
The ADO.net code (not compiled)
Creating table
DataTable dt = new DataTable("Items");
dt.Columns.Add("ID", typeof(int));
dt.Rows.Add(4);
Calling proc
con = new SqlConnection(conStr);
con.Open();
using (con) {
// Configure the SqlCommand and SqlParameter.
SqlCommand sqlCmd = new SqlCommand("czone.SetAccountEmailPreference", con);
sqlCmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParam = sqlCmd.Parameters.AddWithValue("#UnsubscribeTypes", _dt); // TVP
tvpParam.SqlDbType = SqlDbType.Structured; //tells ADO.NET we are passing TVP
//pass other parameters
sqlCmd.ExecuteNonQuery();
}
con.Close();
You will find more about Table-Valued parameters here

Related

How should I get the values from the select query of the stored procedure in c#

I want the date and the name from the select query which if I run as normal query I get the results but i when I try to get the results in C# all I get is count=0. Can anyone tell me what wrong am I doing?
Here is the C# code
private List<CertificationSummary> GetLastAccessData (string taskOwner)
{
List<CertificationSummary> lastAccessedResult = new List<CertificationSummary>();
string connectionString = SqlPlusHelper.GetConnectionStringByName("MetricRepositoryDefault");
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlParameter[] sqlParams = new SqlParameter[1];
sqlParams[0] = new SqlParameter("#taskOwner", SqlDbType.NVarChar);
sqlParams[0].Value = taskOwner;
connection.Open();
SqlCommand cmd = connection.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "GetLastAccessedCertificationData";
cmd.Parameters.AddRange(sqlParams);
cmd.ExecuteNonQuery();
}
return lastAccessedResult;
}
And here is the stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetLastAccessedCertificationData]
(#taskOwner nvarchar(255))
AS
BEGIN
DECLARE #name nvarchar(100)
DECLARE #lastAccessedDate [datetime]
SELECT #name = Name
FROM CertificationReviewCycles
INNER JOIN UserReviewCycleAccess ON CertificationReviewCycles.CertificationReviewCycleID = UserReviewCycleAccess.LastAccessedReviewCycleID
WHERE USERID = #taskOwner
SELECT #lastAccessedDate = LastAccessedDate
FROM UserReviewCycleAccess
WHERE UserID = #taskOwner
CREATE TABLE #tempTable
(
name [nvarchar](255) NULL,
[LastAccessedDate] [datetime] NULL,
)
INSERT INTO #tempTable VALUES (#name, #lastAccessedDate)
SELECT TOP(1) name, LastAccessedDate
FROM #tempTable
END
GO
You are returning lastAccessedResult which is has just been set to new List<CertificationSummary>(). This list has no items, so it has a count of 0.
Use ExecuteReader instead of ExecuteNonQuery and you can then read the data returned and store them into your lastAccessedResult list.
Read here for more info.
ExecuteNonQuery will not return results, and should only be used when you don't expect rows back. This is common for UPDATE statements.
Since you're interested in reading the rows returned by the stored procedure, use ExecuteReader, e.g var reader = cmd.ExecuteReader();
See here for more:
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqldatareader?view=dotnet-plat-ext-3.1
You're using ExecuteNonQuery, which discards any grids from the query. You need to use ExecuteReader to consume grids, but it is a lot of mess and ceremony - the API is verbose. Frankly, I'd recommend a tool like "Dapper" (freely available on NuGet), then this becomes just
private List<CertificationSummary> GetLastAccessData (string taskOwner)
{
string connectionString = SqlPlusHelper.GetConnectionStringByName("MetricRepositoryDefault");
using var connection = new SqlConnection(connectionString);
return connection.Query<CertificationSummary>(
"GetLastAccessedCertificationData",
new { taskOwner }, // <== parameters
commandType: CommandType.StoredProcedure).AsList();
}

One function for multiple stored procedures C#

I have a function that executes stored procedures. The thing is, I wish to use this one function for multiple stored procedures that take different arguments.
Of course, if I do so, I will get an error saying that
Procedure or function has too many arguments specified
What I want to do is to create the function such that when it executes a stored procedure, that stored procedure only takes the parameters that it needs and ignore the others. Is this possible?
Here is what I have so far:
try
{
using (SqlConnection con = new SqlConnection(consr))
{
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = stp;
cmd.Parameters.Add(new SqlParameter("#proc1", cmb1.SelectedItem.ToString()));
cmd.Parameters.Add(new SqlParameter("#proc2", cmb2.SelectedItem.ToString()));
cmd.Parameters.Add(new SqlParameter("#proc3", cmb3.SelectedItem.ToString()));
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;
con.Open();
reader = cmd.ExecuteReader();
con.Close();
}
}
catch (SqlException exp)
{
throw new InvalidOperationException(exp.Message);
}
Here are two of the procedures:
ALTER PROCEDURE [dbo].[test1]
#proc1 varchar(20)
AS
Begin
select * from tab where name=#proc1
END
and
ALTER PROCEDURE [dbo].[test1]
#proc2 varchar(20)
AS
Begin
select * from tab where name=#proc2
END
I want to use the same function to execute both
You can set the params you don't want to use to null, then check for which values are available and respond accordingly
ALTER PROCEDURE [dbo].[test1]
#proc1 varchar(20) = null
#proc2 varchar(20) = null
#proc3 varchar(20) = null
AS
Begin
IF #proc1 IS NOT NULL BEGIN
select * from tab where name=#proc1
END
END
Make your function take two arguments, the name of the SP and a 2d array of SP argument names and their corresponding values. Then set up your sql command by iterating over the 2d array and adding the parameters in the loop.
If you need to return several result sets, see here: How do I return multiple result sets with SqlCommand? and modify the function and args so that they take an array of SP names and an array of 2d arrays, containing the SP arg names and values for each SP.
I think you should use this structure :
CREATE PROCEDURE MyProcName
#Parameter1 INT = 1,
#Parameter2 VARCHAR (100) = 'StringValue',
#Parameter3 VARCHAR (100) = NULL
AS
/* check for the NULL / default value (indicating nothing was passed */
if (#Parameter3 IS NULL)
BEGIN
/* whatever code you desire for a missing parameter*/
INSERT INTO ........
END
/* and use it in the query as so*/
SELECT *
FROM Table
WHERE Column = #Parameter
Can you please share the stored procedure code? I think you need to use if else or case statement in your function and call appropriate stored procedure with required parameters inside your function.

how to write stored procedure with two different queries

Actually i am a beginner in database ..
I have written a stored procedure in which I want to get results in c# winform app from two different tables using if else , for instance I have two tables with one column in common that is 'comp_number' .. now I have written a stored procedure which executes on a button click event
ALTER procedure [dbo].[complainVehicle_sp]
as
DECLARE #compno int
if #compno is not null
begin
select compno,compdate,regno,engineno,mcode from dbo.complainVehicle
where compno = #compno
end
else
begin
select compno,recoverydt,recoverytime,statuscode from dbo.complainRecovery
where compno = #compno
end
Now I want that if Compno matches table complainVehicle it shows me the result against this , and if it matches with table complainRecovery it shows me the result against that record else it will display no record ..
here is my c# code
string str = #"Data Source=.;Initial Catalog=----;Integrated Security=False;User ID=sa;Password=----;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False;";
SqlConnection cnn = null;
try
{
cnn = new SqlConnection(str);
cnn.Open(); //open the connection
}
catch (SqlException err)
{
Console.WriteLine("Error: " + err.ToString());
}
finally
{
if (cnn != null)
{
cnn.Close();
}
}
if (textBox1.Text.Trim().Length == 0)
{MessageBox.Show("No Record");}
else if (textBox1.Text.Trim().Length > 0)
{
cnn.Open();
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = cnn;
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.CommandText = "complainVehicle_sp";
cmd2.Parameters.Add("#compno", System.Data.SqlDbType.NVarChar).Value = textBox1.Text.ToString();
cmd2.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter(cmd2);
DataSet ds = new DataSet();
da.Fill(ds);
dataGridView1.DataSource = ds.Tables[0];
cnn.Close();
As I write compno in textbox and click sumbit it shows an error
`An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Procedure complainVehicle_sp has no parameters and arguments were supplied.`
... i would appreciate you all for this help .. thanks in advance guys
In your code you are using DECLARE #compno int, which creates a local variable within the procedure body. The #compno variable is not accessible from outside of the stored procedure context, and it means nothing to the C# code that is invoking the procedure:
cmd2.Parameters.Add(
"#compno",
System.Data.SqlDbType.NVarChar).Value = textBox1.Text.ToString();
So, to address your issue, first, change the stored procedure to accept parameters.
ALTER PROCEDURE [dbo].[complainVehicle_sp]
-- declare a parameter #compono to the procedure
#compno INT
as ...
BEGIN
IF #compno IS NOT NULL
BEGIN
SELECT compno,compdate,regno,engineno,mcode
FROM dbo.complainVehicle
WHERE compno = #compno
END
ELSE
BEGIN
SELECT compno,recoverydt,recoverytime,statuscode
FROM dbo.complainRecovery
WHERE compno = #compno
END
END
Second, you must add the appropriate parameter type in your C# code:
cmd2.Parameters.Add(
"#compno",
System.Data.SqlDbType.Int).Value = int.Parse(textBox1.Text);
Since the parameter is declared as INT in the stored procedure definition, you need to use System.Data.SqlDbType.Int and provide a valid integer value by calling int.Parse(textBox1.Text).
Refer to T-SQL Stored Procedure Syntax for more information on creating stored procedures and parameter options
Firstly, you have to declare your procedure with a parameter, then you probably want to use EXISTS to check each table, something like this;
alter procedure [dbo].[complainVehicle_sp] (#compno int)
as
if (exists (select 1 from dbo.complainVehicle where compno = #compno ) )
begin
select compno,compdate,regno,engineno,mcode from dbo.complainVehicle
where compno = #compno
end
else
if (exists (select 1 from dbo.complainRecovery where compno = #compno ) )
begin
select compno,recoverydt,recoverytime,statuscode from dbo.complainRecovery
where compno = #compno
end
You also need to specify the type of the parameter correctly;
cmd2.Parameters.Add("#compno", System.Data.SqlDbType.Int).Value = textBox1.Text.ToString();

data insert using input output stored procedure

I am creating a web application using ASP.net C#. I have a booking form and I need to insert data into a table using a Stored Procedure. The table has several columns, out of which second column is a computed column. The Stored Procedure is set up to insert the data and fetch the value from the second column after insert. Below is the code for Stored Procedure:
Create Procedure sp_InsertCashPooja
#FirstName varchar(100),
#LastName varchar(100),
#TelNo bigint,
#Star char(50),
#Rasi char(50),
#Gothram char(50),
#PDMID int,
#PayMode bit,
#PujaName char(50),
#DonateAmt decimal(19,2),
#RcptNo varchar(25) output
as
Begin
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION
if #PujaName != 'DONATION'
Begin
INSERT INTO PoojaDetails (FirstName, LastName, TelNo, Star, Rasi, Gothram, PoojaDietyMasterID, PayMode) values (#FirstName,#LastName,#TelNo,#Star,#Rasi,#Gothram,#PDMID,#PayMode)
End
if #PujaName = 'DONATION'
Begin
DECLARE #isDonate int = 0;
INSERT INTO PoojaDetails (FirstName, LastName, TelNo, Star, Rasi, Gothram, PoojaDietyMasterID, PayMode, isDonate, DonateAmount) values (#FirstName,#LastName,#TelNo,#Star,#Rasi,#Gothram,#PDMID,#PayMode, #isDonate, #DonateAmt)
End
Select #RcptNo = max(ReceiptNo) from PoojaDetails
Return #RcptNo
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF (##TRANCOUNT > 0)
ROLLBACK TRANSACTION
END CATCH
SET NOCOUNT OFF;
End
I would like to insert data on the click of a button: I was able to figure out the below code....
protected void btnSave_Click(object sender, EventArgs e)
{
frmFirstName = txtFirstName.Text.Trim().ToUpper();
frmLastName = txtLastName.Text.Trim().ToUpper();
frmPhoneNo = Convert.ToInt32(txtPhoneNo.Text.Trim());
frmNakshatra = Convert.ToString(cmbNakshatra.SelectedItem).Trim();
frmRasi = Convert.ToString(cmbRasi.SelectedItem).Trim();
frmGothram = Convert.ToString(cmbGothram.SelectedItem).Trim();
frmPujaName = Convert.ToString(cmbPujaName.SelectedItem).Trim();
using (SqlConnection connection = new SqlConnection())
{
if (frmPayMode == "Cash")
{
if (frmPujaName == "DONATION")
{
SqlDataAdapter CashAdapter = new SqlDataAdapter();
CashAdapter.InsertCommand = new SqlCommand("sp_InsertCashPooja", connection);
CashAdapter.InsertCommand.CommandType = CommandType.StoredProcedure;
Please help.... I want to capture the returning RcptNo and later intend to call another ASPX page and pass the value using a Query String.
Thanks
Use simple SqlCommand for calling your SP
connection.Open();
var cmd = new SqlCommand("sp_InsertCashPooja", connection);
cmd.Parameters.AddWithValue("FirstName", frmFirstName);
// Add all the others parameters in same way
var id = (int)cmd.ExecuteScalar();
connection.Close();
Change the return variable to:
Select #RcptNo = SCOPE_IDENTITY()
It will return the identity number created for the inserted record within this procedure.
use sql parameter..
connection = ConfigurationManager.AppSettings["mycon"];
SqlParameter[] para = new SqlParameter[2];
para[0] = new SqlParameter("#stored procedure column name", string name);
para[1] = new SqlParameter("#stored procedure column name", string name);

Passing Parameters through stored Procedure

I am new to interfacing DB's with applications and am trying to pull a couple of fields from a database where the parameter I specified should filter out the results. I keep receiving a no parameters or arguments were supplied. Can anyone shed a little insight on this? Thanks.
below is the stored procedure:
ALTER PROC dbo.PassParamUserID
AS
set nocount on
DECLARE #UserID int;
SELECT f_Name, l_Name
FROM tb_User
WHERE tb_User.ID = #UserID;
And here is my code
class StoredProcedureDemo
{
static void Main()
{
StoredProcedureDemo spd = new StoredProcedureDemo();
//run a simple stored procedure that takes a parameter
spd.RunStoredProcParams();
}
public void RunStoredProcParams()
{
SqlConnection conn = null;
SqlDataReader rdr = null;
string ID = "2";
Console.WriteLine("\n the customer full name is:");
try
{
//create a new connection object
conn = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=c:\\Program Files\\Microsoft SQL Server\\MSSQL10.SQLEXPRESS\\MSSQL\\DATA\\UserDB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True; Integrated Security=SSPI");
conn.Open();
//create command objects identifying the stored procedure
SqlCommand cmd = new SqlCommand("PassParamUserID", conn);
//Set the command object so it know to execute the stored procedure
cmd.CommandType = CommandType.StoredProcedure;
//ADD PARAMETERS TO COMMAND WHICH WILL BE PASSED TO STORED PROCEDURE
cmd.Parameters.Add(new SqlParameter("#UserID", 2));
//execute the command
rdr = cmd.ExecuteReader();
//iterate through results, printing each to console
while (rdr.Read())
{
Console.WriteLine("First Name: {0,25} Last Name: {0,20}", rdr["f_Name"], rdr["l_Name"]);
}
}
You need to modify your SQL stored proc to:
ALTER PROC dbo.PassParamUserID
#UserID int
AS set nocount on
SELECT f_Name, l_Name FROM tb_User WHERE tb_User.ID = #UserID;
At the moment you are just declaring it as a variable within the procedure.
Here are some MSDN articles that may help you going forward:
Creating and Altering Stored procedures
Declaring Local Variables
ALTER PROC dbo.PassParamUserID (#UserID int)
AS
set nocount on
SELECT f_Name, l_Name FROM tb_User WHERE tb_User.ID = #UserID;
If you want to pass a parameter in you need to define it before the AS statement as shown above.

Categories