how to get Stored Procedure output parameter in c# - c#

I am trying to get the value of output parameter of a stored procedure in c# function. when i execute the SP i am getting correct result in sql server but i can't get in c#. Can you please tell me how can i get the output value in c#. Below is the function i am trying to get the output value in C# DAC.
public DataSet GetOrderItemPictureByOrderId(int orderID, int PageIndex)
{
DataSet dtOrder = new DataSet();
/// Connect to database.
Database db = DatabaseFactory.CreateDatabase(CONNECTION_NAME);
using (DbCommand cmd = db.GetStoredProcCommand("uspGetOrderItemPicturePageWise"))
{
/// Set parameter values.
db.AddInParameter(cmd, "#OrderID", DbType.Int32, orderID);
db.AddInParameter(cmd, "#PageIndex", DbType.Int32, PageIndex);
db.AddInParameter(cmd, "#PageSize", DbType.Int32, 6);
db.AddOutParameter(cmd, "#RecordCount", DbType.Int32, 4);
try
{
dtOrder = db.ExecuteDataSet(cmd);
string outputValue = cmd.Parameters["#RecordCount"].Value.ToString(); // here i want to get the output value and want to return the value to main code
}
catch (Exception ex)
{
LogErrors.WriteError(ex);
}
}
return dtOrder;
}
}
Here i am calling the function :-
DataSet _ds = _orderPicDAC.GetOrderItemPictureByOrderId(OrderID, PageIndex);
My Store Procedure :--
CREATE PROCEDURE [dbo].[uspGetOrderItemPicturePageWise]
#OrderID int,
#PageIndex INT = 1
,#PageSize INT = 10
,#RecordCount INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT ROW_NUMBER() OVER
(
ORDER BY [PictureId] ASC
)AS RowNumber,
Orderid,
GenericFieldID,
ItemImage
INTO #Results
FROM [OrderPictures]
WHERE OrderID = #OrderID
SELECT #RecordCount = COUNT(*)
FROM #Results
SELECT * FROM #Results
WHERE RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
DROP TABLE #Results
END
Thanks for your help in advance.

If you want to get value of output parameter outside the method without changing the return type of the method, you may use out parameters in C#.
Change your method definition like below:
public DataSet GetOrderItemPictureByOrderId(int orderID, int PageIndex, out string outputValue)
{
//code here
outputValue = db.GetParameterValue(cmd, "#RecordCount");
//code here
}
and then call this method
string outvalue;
DataSet _ds = _orderPicDAC.GetOrderItemPictureByOrderId(OrderID, PageIndex,out outvalue;);
You will have the value in outvalue variable.

You can try with below
using (SqlConnection con = new SqlConnection(dc.Con))
{
using (SqlCommand cmd = new SqlCommand("SP_ADD", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#OrderID", DbType.Int32, orderID);
con.Open();
cmd.ExecuteNonQuery();
}
}

Related

Oracle function return rows into c#

I want to create a procedure or function in oracle that returns more than one row of different types to my application. I found some examples on the internet but i can't get it to work...
Example:
I created a custom type in oracle:
create type proc_selectall is object
(Mjera varchar2(50),
Status number(10,0),
Naziv varchar2(50),
Stat number(10,0));
Then:
create type ret_selectall is table of proc_selectall;
Then created function:
create or replace function fsp_SelectAll return ret_selectall
is
l_ret_selectall ret_selectall := ret_selectall();
n integer := 0;
BEGIN
for r in(SELECT JEDINICAMJERE.Mjera,
JEDINICAMJERE.Status,
KATEGORIJE.Naziv,
KATEGORIJE.Status as Stat
FROM JEDINICAMJERE, KATEGORIJE)
loop
l_ret_selectall.extend;
n := n + 1;
l_ret_selectall(n) := proc_selectall(r.Mjera, r.Status, r.Naziv, r.Stat);
end loop;
return l_ret_selectall;
END;
When I type this line:
select * from table (fsp_SelectAll)
I get a nice and expected output:
MJERA | STATUS | NAZIV | STAT
tr 0 name1 1
fd 1 name2 1
ds 1 name3 0
.....
Later i tried to get those values in my app.
I tried something like this:
//cmd.Parameters.Add("proc_selectall ", OracleDbType.Object);
//cmd.Parameters.Add("ret_selectall ", OracleDbType.Array);
//cmd.Parameters["ret_selectall "].Direction = ParameterDirection.ReturnValue;
//if (connection.State == ConnectionState.Closed)
// connection.Open();
//cmd.ExecuteNonQuery();
Later this...
//OracleCommand objCmd = new OracleCommand("select * from table fsp_SelectAll", connection);
//objCmd.CommandType = CommandType.StoredProcedure;
//objCmd.ExecuteNonQuery();
//int size=objCmd.ExecuteReader().FieldCount;
I also tried with
//adapter = new OracleDataAdapter(cmd);...
But there are always some errors about type, parameters...
(Connection to oracle work. I executed Insert, Update, Delete procedures and they work fine)
Also i tried to create this procedure: (this was my first try)
CREATE OR REPLACE PROCEDURE osp_SelectAll (Mjera OUT VARCHAR2,
Status OUT NUMBER, Naziv OUT VARCHAR2,Stat OUT NUMBER) AS
BEGIN
SELECT JEDINICAMJERE.Mjera,
JEDINICAMJERE.Status,
KATEGORIJE.Naziv,
KATEGORIJE.Status as Stat INTO Mjera, Status, Naziv, Stat
FROM JEDINICAMJERE, KATEGORIJE;
END osp_SelectAll;
But it doesn't return any row or rows... and i give up.
Please help me, i need to solve this.
Returning a user defined object is not so easy, it requires a lot of additional effort.
Try this one:
create or replace function fsp_SelectAll return SYS_REFCURSOR is
res SYS_REFCURSOR;
BEGIN
OPEN res FOR
SELECT JEDINICAMJERE.Mjera,
JEDINICAMJERE.Status,
KATEGORIJE.Naziv,
KATEGORIJE.Status as Stat
FROM JEDINICAMJERE, KATEGORIJE;
return res;
END;
and then
OracleCommand objCmd = new OracleCommand("fsp_SelectAll", connection);
objCmd.CommandType = CommandType.StoredProcedure;
objCmd.Parameters.Add("res", OracleDbType.RefCursor, ParameterDirection.ReturnValue);
var da = new OracleDataAdapter(objCmd);
var dt = new DataTable();
da.Fill(dt);
Or you can use ExecuteReader(), if you prefer:
OracleDataReader dr = objCmd.ExecuteReader();
while ( dr.Read() ) {
...
}
dr.Close();
Note, I never worked with .CommandType = CommandType.StoredProcedure;. If it fails use this syntax:
OracleCommand objCmd = new OracleCommand("BEGIN :res := fsp_SelectAll; END;", connection);
objCmd.CommandType = CommandType.Text;

Returning the row id from stored procedure in C#?

I'm trying to get the row id of a row that is inserted.
This is the Fuel class:
public class Fuel
{
private Int32 fuelId;
private DateTime fuelDate;
public Fuel(DateTime fuelDate)
{
this.fuelDate = fuelDate;
}
public Fuel(Int32 fuelId, DateTime fuelDate)
{
this.fuelId = fuelId;
this.fuelDate = fuelDate;
}
public Int32 FuelId() { return fuelId; }
public DateTime FuelDate() { return fuelDate; }
}
This is the method that is trying to write to the database:
protected String connectionString = #"Data Source=(LocalDB)\MSSQLLocalDB;
AttachDbFilename=" + "C:\\Users\\keith_000\\Documents\\Visual Studio 2017\\Projects\\RubberDress\\RubberDress\\Rubber.mdf" + ";" +
"Integrated Security=True;" +
"Connect Timeout=30";
public Int32 InsertFuelPurchase(Fuel myAddFuel)
{
Int32 myFuelId;
using (SqlConnection mySqlConn = new SqlConnection(connectionString))
{
mySqlConn.Open();
using (SqlCommand myComm = new SqlCommand("FUELINSERT", mySqlConn))
{
myComm.CommandType = CommandType.StoredProcedure;
myComm.Parameters.Add("#FUELDATE", SqlDbType.DateTime).Value = myAddFuel.FuelDate();
myComm.Parameters.Add("#FUELID", SqlDbType.Int).Direction = ParameterDirection.Output;
myFuelId = Convert.ToInt32(myComm.Parameters["#FUELID"].Value);
mySqlConn.Close();
}
}
return myFuelId;
}
The stored procedure is
CREATE PROCEDURE [dbo].[FUELINSERT]
#FUELDATE DATETIME,
#FUELID INT OUTPUT
AS
INSERT INTO FUELPURCHASE (FUELPURCHASEDATE)
VALUES (#FUELDATE)
SELECT #FUELID = SCOPE_IDENTITY()
Which is writing to the following table
CREATE TABLE [dbo].[FUELPURCHASE]
(
[FUELPURCHASEID] INT IDENTITY (1, 1) NOT NULL,
[FUELPURCHASEDATE] DATETIME NOT NULL
PRIMARY KEY CLUSTERED ([FUELPURCHASEID] ASC)
);
Currently the result which is being returned is 0.
When I debug the method I find it 0 is being returned from the stored procedure.
Can anyone spot where I have to resolve the problem?
Of course you need to execute the command, (ExecuteScalar, ExecuteNonQuery, even ExecuteReader will call the SP and runs your SqlCommand) but you don't need to have an out parameter, just SELECT SCOPE_IDENTITY() in the stored procedure and execute the command with ExecuteScalar
CREATE PROCEDURE [dbo].[FUELINSERT]
#FUELDATE DATETIME
AS
INSERT INTO FUELPURCHASE (FUELPURCHASEDATE) VALUES (#FUELDATE)
SELECT SCOPE_IDENTITY()
Now you can call the SP with
....
using (SqlCommand myComm = new SqlCommand("FUELINSERT", mySqlConn))
{
myComm.CommandType = CommandType.StoredProcedure;
myComm.Parameters.Add("#FUELDATE", SqlDbType.DateTime).Value = myAddFuel.FuelDate();
myFuelId = Convert.ToInt32(myComm.ExecuteScalar());
}
....
You are missing myComm.ExecuteNonQuery();...your code should looks like:
myComm.ExecuteNonQuery();
myFuelId = Convert.ToInt32(myComm.Parameters["#FUELID"].Value);
try this:
mySqlConn.Open();
using (SqlCommand myComm = mySqlConn.CreateCommand())
{
myComm.CommandType = CommandType.StoredProcedure;
myComm.CommandText = "Exec YourProcedure #FUELDATE,#FUELID";
myComm.Parameters.Add("#FUELDATE", SqlDbType.DateTime).Value = myAddFuel.FuelDate();
myComm.Parameters.Add("#FUELID", SqlDbType.Int).Direction = ParameterDirection.Output;
myFuelId = Convert.ToInt32(myComm.Parameters["#FUELID"].Value);
int result = myComm.ExecuteNonQuery();
mySqlConn.Close();
return result;
}
when returning a single value use myComm.ExecuteScalar()
It is depend on your FUELDATE, FUELID position:

Issues in insert function in SQL Server and C#

C#:
protected void btnsearch_Click(object sender, EventArgs e)
{
SqlConnection con = Connection.DBconnection(); {
SqlCommand com = new SqlCommand("sp_studentresult", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#id", textstudentid.Text);
com.Parameters.AddWithValue("#id_student", textstudentid.Text.Trim());
SqlParameter retval = new SqlParameter("#output", SqlDbType.VarChar, 50);
com.Parameters.AddWithValue("#tamil", txttamil.Text.Trim());
com.Parameters.AddWithValue("#english", txtenglish.Text.Trim());
com.Parameters.AddWithValue("#maths", txtmaths.Text.Trim());
com.Parameters.AddWithValue("#science", txtscience.Text.Trim());
com.Parameters.AddWithValue("#socialScience", txtsocialscience.Text.Trim());
retval.Direction = ParameterDirection.Output;
com.Parameters.Add(retval);
com.ExecuteNonQuery();
string Output = retval.Value.ToString();
textstudentid.Text = string.Empty;
txttamil.Text = string.Empty;
txtenglish.Text = string.Empty;
txtmaths.Text = string.Empty;
txtscience.Text = string.Empty;
txtsocialscience.Text = string.Empty;
SqlDataAdapter adp = new SqlDataAdapter(com);
DataSet ds = new DataSet();
adp.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
tblid.Visible = true;
txtid.Text = ds.Tables[0].Rows[0]["id"].ToString();
txttamil.Text = ds.Tables[0].Rows[0]["Tamil"].ToString();
txtenglish.Text = ds.Tables[0].Rows[0]["English"].ToString();
txtmaths.Text = ds.Tables[0].Rows[0]["Maths"].ToString();
txtscience.Text = ds.Tables[0].Rows[0]["Science"].ToString();
txtsocialscience.Text = ds.Tables[0].Rows[0]["SocialScience"].ToString();
}
else
{
tblid.Visible = false;
output.Text = Output;
}
}
What I have done:
Step 1
When I enter invalid id (which means id doesnot contain in student table) and search, it shows "doesn't exist".
Step 2
When I enter valid id (which means id contains in student and also contain in studentresult table) and search, it shows student marks, if I want to edit the marks and update, so it shows "marks updated".
Step 3
But when I enter id (which means id contains in student but doesn't contain in studentresult table) and search, it works updated function again with all the textboxes contains 0, instead it works insertion.
May I know, what my mistake in the above code?
Can anyone guide me?
I'm struggling for an hour, I'm beginner in .net.
Thanks,
sp_studentresult is broken: it should not insert into studentresult if there already is a row for the given id. Just add
AND NOT EXISTS (SELECT * FROM studentresult WHERE id_student=#id_student)
to
ELSE IF EXISTS (SELECT * FROM student WHERE id=#id_student)
Resulting to:
ALTER PROCEDURE sp_studentresult
(
#id int,
#output varchar(50) output,
#id_student varchar(50),
#Tamil Varchar (100),
#English varchar (50),
#Maths Varchar (50),
#Science Varchar (50),
#SocialScience Varchar (50)
)
AS
IF NOT EXISTS (SELECT * FROM student WHERE id=#id_student)
BEGIN
SET #output='Doesn not EXIST'
END
ELSE IF EXISTS (SELECT * FROM student WHERE id=#id_student)
AND NOT EXISTS (SELECT * FROM studentresult WHERE id_student=#id_student)
BEGIN
INSERT into studentresult (id_student,Tamil,English,Maths,Science,SocialScience) values (#id_student,#Tamil,#English,#Maths,#Science,#SocialScience)
SET #output='Inserted'
END
SELECT * from studentresult where id_student=#id

Failed to get result of stored procedure

I created a procedure that returns the ID of the Question based on the input text
ALTER PROCEDURE [dbo].[GetQuestionIDbyTekst]
(
#Tekst nvarchar(100)
)
AS
DECLARE #QuestionID int
SELECT QuestionID
FROM dbo.Questions
WHERE Tekst = #Tekst
RETURN #QuestionID
and I have a problem in getting the value of the QuestionID:
public static int getQuestionID(Question p)
{
using (Entities dm = new Entities())
{
return dm.GetQuestionIDbyTekst(p.Tekst);
}
}
Make the #QuestionID as Output parameter. Also you need to assign the result to #QuestionID
ALTER PROCEDURE [dbo].[GetQuestionIDbyTekst]
(
#Tekst nvarchar(100),
#QuestionID INT OUTPUT
)
AS
BEGIN
DECLARE #QuestionID int
SELECT #QuestionID = QuestionID FROM dbo.Questions WHERE Tekst = #Tekst
END
please try this:
ALTER PROCEDURE [dbo].[GetQuestionIDbyTekst]
(
#Tekst nvarchar(100)
)
AS
-- DECLARE #QuestionID int
SELECT QuestionID
FROM dbo.Questions
WHERE Tekst = #Tekst
-- RETURN #QuestionID
You can use your variant of the stored procedure.
And if you use ADO.NET and want to get return value, try this:
SqlConnection con = new SqlConnection(#"Data Source=localhost\***;Initial Catalog=***;Integrated Security=True;Persist Security Info=False;");
con.Open();
SqlCommand cmd = new SqlCommand("GetQuestionIDbyTekst", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#Tekst", System.Data.SqlDbType.NVarChar).Value = "eee";
SqlParameter returnPar = new SqlParameter();
returnPar.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(retturnPar);
cmd.ExecuteScalar();
var result = returnPar.Value;
If you use Entity Framework, you may use this variant:
public static int GetQuestionIDbyTekst(string question)
{
using (var context = new EfDbContext())
{
var test = new SqlParameter("#Tekst", question);
var resultParam = new SqlParameter("#result", SqlDbType.Int);
resultParam.Direction = ParameterDirection.Output;
context.Database.ExecuteSqlCommand("exec #result = [dbo].[testProc] #Tekst", resultParam, test);
return (int)resultParam.Value;
}
}

Executing SQL Stored Procedure

ALTER PROCEDURE dbo.SP_InsertTicket
/*
(
#parameter1 int = 5,
#parameter2 datatype OUTPUT
)
declare #i as numeric
exec SP_InsertTicket 'asd','cd#y.com','232323','dasasd','sdasdas','01-jan-2010',#i output,'sdas','sdasd','02-jan-2010'
select #i*/
#Client_FullName varchar(30),
#Client_EmailAdd varchar(50),
#Client_Telephn varchar(15),
#Ticket_Subject varchar(50),
#Ticket_Source varchar(15),
#Ticket_CreateDate Datetime,
#Ticket_Id integer output,
#Que_Message varchar(100),
#Que_Attachment varchar(max),
#Que_UpdateDate Datetime
AS
declare #TickID integer;
/* SET NOCOUNT ON */
BEGIN
INSERT INTO tbl_Ticket (Client_FullName,Client_EmailAdd,Client_Telephn,Ticket_Subject,Ticket_Source,Ticket_CreateDate)
VALUES (#Client_FullName, #Client_EmailAdd ,#Client_Telephn,#Ticket_Subject,#Ticket_Source,#Ticket_CreateDate)
Select #TickID = MAX(Ticket_Id) from tbl_Ticket
set #Ticket_Id=#TickID
INSERT INTO tbl_TicketQuestion (Ticket_Id,Que_Message,Que_Attachment,Que_UpdateDate)
VALUES (#TickID,#Que_Message,#Que_Attachment,#Que_UpdateDate)
END
RETURN
This is my store procedure in which i need to return Ticket_Id to send it via email app
It insert records well bt not able to retirn value in DAL
Below is the code for executing stored procedure which returns value
public class cls_DAL
{
public cls_DAL()
{
//
// TODO: Add constructor logic here
//
}
static string strConn = System.Configuration.ConfigurationManager.ConnectionStrings["conString"].ConnectionString.ToString();
SqlConnection con = new SqlConnection(strConn);
SqlCommand cmd = new SqlCommand();
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
public int insert_NewTicket(string fullname, string emailadd, string telephone, string subject, string source, DateTime date,string Message, string attachment, DateTime updatedate)
{
try
{
con.Open();
cmd = new SqlCommand("SP_InsertTicket", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Client_FullName", fullname);
cmd.Parameters.AddWithValue("#Client_EmailAdd", emailadd);
cmd.Parameters.AddWithValue("#Client_Telephn",telephone);
cmd.Parameters.AddWithValue("#Ticket_Subject", subject);
cmd.Parameters.AddWithValue("#Ticket_Source",source);
cmd.Parameters.AddWithValue("#Ticket_CreateDate",date);
cmd.Parameters.AddWithValue("#Ticket_Id",0);
cmd.Parameters.AddWithValue("#Que_Message", Message);
cmd.Parameters.AddWithValue("#Que_Attachment", attachment);
cmd.Parameters.AddWithValue("#Que_UpdateDate",updatedate);
cmd.Parameters["#Ticket_Id"].Direction = ParameterDirection.InputOutput;
return cmd.ExecuteNonQuery();
int i = (int)cmd.Parameters["#Ticket_Id"].Value;
}
catch
{
throw;
}
finally
{
cmd.Dispose();
con.Close();
con.Dispose();
}
}
}
Its just a guess, not sure. You can give a try the following:
cmd.Parameters["#Ticket_Id"].Direction = ParameterDirection.InputOutput;
TO
cmd.Parameters["#Ticket_Id"].Direction = ParameterDirection.Output;
That won't compile you'll get unreachable code
cmd.Parameters["#Ticket_Id"].Direction = ParameterDirection.InputOutput; cmd.ExecuteNonQuery();
return (int)cmd.Parameters["#Ticket_Id"].Value;
or #Matt's solution below...
That cast is iffy as well...
And in a multi user scenario, ticketid will race.
Think about what could (will!!!) happen if you run two of these at the same time
Should be wrapped in a transaction.
And you don't need Max, either, Use Scope_Identity
You could run Select Scope_Identity() after the Insert statement. Then in your DAL Method return Convert.ToInt32(cmd.ExecuteScalar())
Change this:
return cmd.ExecuteNonQuery();
to
Int i = cmd.ExecuteScalar();
If you are only returning one integer from that procedure.
ExecuteNonQuery() isnt the method you want to be using here

Categories