Saving a result from stored procedure in code behind - c#

I want to retrieve a project id from my project table in SQL Server.
I created a stored procedure like this:
create proc spFindProjectID
(#customerid int)
as
begin
select Project.pID
from Project
where Project.cID=#customerid
end
Now in my C# I execute that proc like this:
public int findid(int id)
{
con = connect("igroup9_test1ConnectionString");
using (SqlCommand sqlComm = new SqlCommand("[spFindProjectID]", con))
{
if (con.State != ConnectionState.Open)
{
con.Open();
}
try
{
sqlComm.CommandType = CommandType.StoredProcedure;
sqlComm.Parameters.AddWithValue("#customerid", id);
sqlComm.CommandTimeout = 600;
sqlComm.ExecuteNonQuery();
}
catch (Exception ex)
{
throw (ex);
}
return
}
}
I want to save the result from the procedure and return it.
How can I do this?

Let's have a look at the documentation for ExecuteNonQuery:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. ... For all other types of statements, the return value is -1.
You're calling a stored procedure, which is none of the 3 listed statements.
I assume your
select Project.pID
from Project
where Project.cID=#customerid
query returns only one cell, you can use SqlCommand.ExecuteScalar method which returns the first column of the first row as object.
For example;
sqlComm.CommandType = CommandType.StoredProcedure;
sqlComm.Parameters.AddWithValue("#customerid", id);
int value = (int)sqlComm.ExecuteScalar();
return value;

Related

PL/SQL - Oracle: Stored procedure returning dataset from various tables

What I need:
In PLS/SQL on an Oracle DB, create a stored procedure or function with parameters, which given a declared table of , where is a ROW of a table (with all the fields), returns the resultset following the conditions given in the parameters. After, I need to call them from Microsoft Entity Framework with edmx file.
Basically the need is to being able to provide a quick report of the table contents into a pdf, matching some filters, with an oracle db.
The mantainer must be able, provided a script I give, to create and add new reports, so this needs to be dynamic.
Here's what I've got so far:
CREATE OR REPLACE type THETABLEIWANTTYPE as table of THETABLEIWANT%TYPE
create function
SCHEMA.THETABLEIWANT_FUNCTION(PARAM_GR in number default 1)
return THETABLEIWANTTYPE
PIPELINED
as
result_table THETABLEIWANTTYPE
begin
SELECT S.id, S.idg, S.sta, S.tab
Bulk collect into result_table
from SCHEMA.THETABLEIWANT S
WHERE IDGR = PARAM_GR
IF result_table.count > 0 THEN
for i in result_table.FIRST .. result_table.LAST loop
pipe row (result_table(i))
end loop
end if
return
end;
But it's not working. It gives errors.
Running CREATE TYPE I get:
Compilation errors for TYPE SCHEMA.THETABLEIWANT
Error: PLS-00329: schema-level type has illegal reference to
SCHEMA.THETABLEIWANT
The mantainer will launch the script creating a TYPE of the row of the table I need, then the function should return a table with the records.
Then calling it from Entity Framework I should be able to execute it like I'm calling a normal select from my table, IE:
``_dbContext.THETABLEIWANT.Where(x => x.IDGR = Param_gr).ToList();
The problem is that mantainers should be able to generate new kind of reports with any select inside without the need of my intervention on the software code.
Any hint?
It's ok also to bulk all the select result into a temp table but it has to be dynamic as column will be changing
I ended up to write a PLS/SQL procedure that returns a cursor and managing it from C# code with Oracle.ManagedDataAccess Library.
Here's the procedure, for anyone interested:
CREATE OR REPLACE PROCEDURE SCHEMA.PROC_NAME(
PARAM_1 VARCHAR2,
RESULT OUT SYS_REFCURSOR)
IS
BEGIN
OPEN RESULT FOR
SELECT A, V, C AS MY_ALIAS from SCHEMA.TABLE WHERE FIELD = PARAM_1 AND FIELD_2 = 'X';
END;
And here's the C# code for calling and getting the result:
OracleConnection conn = new OracleConnection("CONNECTIONSTRING");
try
{
if (conn.State != ConnectionState.Open)
conn.Open();
List<OracleParameter> parametri = new List<OracleParameter>()
{
new OracleParameter
{
ParameterName = nameof(filter.PARAM_1),
Direction = ParameterDirection.Input,
OracleDbType = OracleDbType.NVarchar2,
Value = filter.PARAM_1
}
};
OracleCommand cmd = conn.CreateCommand();
cmd.Parameters.AddRange(parametri.ToArray());
OracleParameter cursor = cmd.Parameters.Add(
new OracleParameter
{
ParameterName = "RESULT",
Direction = ParameterDirection.Output,
OracleDbType = OracleDbType.RefCursor
}
);
cmd.CommandText = procedureName;
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
using (OracleDataReader reader = ((OracleRefCursor)cursor.Value).GetDataReader())
{
if (reader.HasRows)
while (reader.Read())
{
//Iterate the result set
}
}
}
catch(Exception ex)
{
//Manage exception
}

How do i display a select stored procedure result in a textbox?

I need to display the result from a select statement in a stored procedure onto the textbox and I can't figure out how to do it. The select statement doesn't use a WHERE clause. The stored procedure goes
CREATE PROCEDURE NewCustomer
AS
BEGIN
SELECT MAX(ID) + 1 FROM Database
END
This is what I've tried
protected void btnNew_Click(object sender, EventArgs e)
{
Clear();
int num;
try
{
using (SqlCommand command = new SqlCommand("NewCustomer"))
{
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#CustID", SqlDbType.Int).Value = Int32.TryParse(txtCID.Text, out num); // Use tryparse if needed
conn.Open();
txtCID.Text = (string)command.ExecuteScalar();
}
}
catch (Exception ex)
{
lblMessage.Text = ex.Message;
}
}
It gives me a "Procedure NewCID has no parameters and arguments were supplied." Error
You are not executing the procedure that you ware given. The procedure is named as yadayada(The worst name that you can give) and you are executing the procedure NewCustomer as the command text. Both has to be same. Then you are using the Wrong statement for executing the query.
The ExecuteNonQuery to perform catalog operations (for example,
querying the structure of a database or creating database objects such
as tables), or to change the data in a database without using a
DataSet by executing UPDATE, INSERT, or DELETE statements.
But you are using it for executing the select query. Here you are selecting a single value from the table so the ExecuteScalar will be the best option for you. Your code will be like this: assume the procedure name is GetNewCustomerID;
using (SqlCommand exeCommand = new SqlCommand("GetNewCustomerID"))
{
exeCommand.Connection = conn;
exeCommand.CommandType = CommandType.StoredProcedure;
exeCommand.Parameters.Add("#CustID",SqlDbType.Int).Value=Convert.ToInt32(txtCID.Text); // Use tryparse if needed
conn.Open();
txtCID.Text = (string)exeCommand.ExecuteScalar();
}

Unable to get data from stored procedure

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.
}

Why this query returning -1?

I'm trying to get the max id of the table category using this code
string maxid = "";
string query = "SELECT MAX(Cat_ID) + 1 FROM Category";
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["JokerCafe"].ConnectionString);
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(query, conn);
maxid = cmd.ExecuteNonQuery().ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
conn.Close();
}
return maxid;
I run this query in sql it is returning exact value but when try to execute it from code it returns -1. Kindly guide me what's going wrong with it?
ExecuteNonQuery() will return the affected row count. For example if you are trying to execute any update statement or delete statement through ExecuteNonQuery() method then it will return the number of affected rows.
But, if you want to fetch a value from specific field then you need to try ExecuteScalar() method. It will return Object type value. Using this method you can fetch only a single value record.
object val = command.ExecuteScalar();
if (val != null)
{
//Do your stuff here.
}
ExecuteScaler is your solution
It executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored.
so do modify your code to
maxid = cmd.ExecuteScalar().ToString();
or
maxid = cmd.ExecuteScalar() as string; //to be safe side if return value is null
and you'll get the value expected from the query

Get Multiple Values From Database ASP.NET/C#

I am trying to get/return multiple values from an SQL-Server database using and display them on an ASP.NET page.
I am using a stored procedure to perform the SELECT command on the Database side.
I am able to return the first value that matches the variable #PERSON but only one row is returned each time.
Any help would be much appreciated.
Database handler class
public MainSQL()
{
_productConn = new SqlConnection();
_productConnectionString += "data source=mssql.database.co.uk;InitialCatalog=test_data;User ID=username;Password=password";
_productConn.ConnectionString = _productConnectionString;
}
public string GetItemName(int PersonID)
{
string returnvalue = string.Empty;
SqlCommand myCommand = new SqlCommand("GetItem", _productConn);
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.Add(new SqlParameter("#PERSON", SqlDbType.Int));
myCommand.Parameters[0].Value = PersonID;
_productConn.Open();
returnvalue = (string)myCommand.ExecuteScalar();
_productConn.Close();
return (string)returnvalue;
}
Stored Procedure
USE [test_data]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [ppir].[GetItem]
(
#PERSON int
)
AS
/*SET NOCOUNT ON;*/
SELECT Description FROM [Items] WHERE PersonID = #PERSON
RETURN
return.aspx
namespace test
{
public partial class Final_Page : System.Web.UI.Page
{
MainSQL GetInfo;
protected void Page_Load(object sender, EventArgs e)
{
int PersonId = (int)Session["PersonID"];
GetInfo = new MainSQL();
string itemname = GetInfo.GetItemName(PersonId);
ReturnItemName.Text = itemname;
} // End Page_Load
} // End Class
} // End Namespace
you should use sql datareader instead.:
ExecuteScalar returns you only the first result while reader returns you each result by loop until
reader.Read()==false.
e.g. :
DataReader data_reader= MySqlCommand.ExecuteReader( );
while(data_reader.Read())
{
...
}
I Change your GetItem method like this :
public List<string> GetItemName(int PersonID)
{
List<string> returnvalues = new List<string>();
SqlCommand myCommand = new SqlCommand("GetItem", _productConn);
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.Add(new SqlParameter("#PERSON", SqlDbType.Int));
myCommand.Parameters[0].Value = PersonID;
_productConn.Open();
DataReader dr = myCommand.ExecuteReader();
While(dr.Read() )
{
returnvalues.Add(dr[0].ToString());
}
_productConn.Close();
return returnvalues;
}
Does your stored procedure return one row for the id or does it return multiple rows? Ultimately you will need to loop over your results. If the stored procedure returns one record per call, then you need to loop over the ids in the aspx page. If the stored procedure returns multiple rows, then you can use and sqlDataReader instead of the ExecuteScalar call. Loop over the rows that were return and add them to some sort of a collection or list. Then return it to your page. You will still have to modify your aspx page to handle the collection, however.
You could use a SQLDataReader, or a SQLDataAdapter to fill in a DataSet, although for webforms you might be better served by separating your data access from your page entirely by way of using an ObjectDataSource.

Categories