Stored Procedure returns nothing - c#

This might be a simple fail on my part, but I just can't figure out where or how.
I've been coding a windows service that is doing a bunch of things. One of which is inserting and getting data from a MS Sql 2005 database through stored procedures.
The following code is part of a windows service and now also a windows form, where both produce the same empty result.
try
{
SqlCommand cmd = new SqlCommand("U_RfId_ProductNumberGet", connectionRFID);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
//SqlParameter paramProd = new SqlParameter();
SqlParameter paramOut = new SqlParameter();
paramOut.ParameterName = "#ProductInformation";
paramOut.Direction = System.Data.ParameterDirection.Output;
paramOut.SqlDbType = System.Data.SqlDbType.VarChar;
paramOut.Size = 50;
cmd.Parameters.Add(paramOut);
cmd.Parameters.AddWithValue("#ProductNumber", content); //content = "1" for testing
connectionRFID.Open();
textBox1.Text = (String)paramOut.Value;
//cmd.Parameters["#ProductInformation"].Value.ToString();
connectionRFID.Close();
}
catch (Exception ex)
{ textBox1.Text = ex.Message;
connectionRFID.Close();
}
And then there's the SP the code is calling. I've tried changing it to only return a resultset instead of a scalar output parameter and then the call to the SP works, but I'd prefer to use the scalar values.
CREATE PROCEDURE U_RfId_ProductNumberGet
#ProductInformation varchar(50) OUTPUT,
#ProductNumber varchar(8)
AS
BEGIN TRAN
SET NOCOUNT ON;
BEGIN
SELECT #ProductInformation
= CAST(vareNummer AS varchar(10))
+ '-' + CAST(vareTekst AS varchar(30))
FROM VareNummerVareTekst
WHERE ProductNumber = #ProductNumber
END
COMMIT TRAN
As a side note: If I execute the SP through SQL Management Studio I get a valid result.
Anyone notice what I've forgotten?

You forgot to execute the command.
cmd.Execute(); // to get a resultset
or
cmd.ExecuteNonQuery(); // to get output parameters but no resultset
should do it depending on whether or not you want a resultset.

you have to use ExecuteNonQuery on command object. SqlCommand Executenonquery
connectionRFID.Open();
cmd.ExecuteNonQuery(); // this missing from your code
textBox1.Text = (String)paramOut.Value;

Related

oracle character to number conversion error from .net

I have a procedure in oracle having input fields varchar2 and number. I am adding parameters from my .Net code using Oracle.DataAccess.dll. I am getting an exception like
ORA-06502: PL/SQL: numeric or value error: character to number conversion error\nORA-06512: at line 1
If I run procedure directly from oracle sql developer, it works fine.
code:-
OracleCommand cmd = (OracleCommand)_dbFactory.CreateCommand();
try
{
cmd.Connection = (OracleConnection)_conOracle;
_conOracle.Open();
cmd.CommandText = "SERVICE_STATUS";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Clear();
cmd.Parameters.Add("PANUMBER", OracleDbType.Int32).Value = 10;
cmd.Parameters.Add("PA_LINK", OracleDbType.Varchar2).Value = "Test";
cmd.Parameters.Add("PO_MSG", OracleDbType.Varchar2, 4000).Direction = System.Data.ParameterDirection.Output;
try
{
cmd.ExecuteScalar();
}
catch(Exception ex1) {
log.Debug("Exception ex1 "+ ex1.Message+" inner--"+ex1.InnerException);
}
string isValid = cmd.Parameters["PO_MSG"].Value.ToString();
if (isValid == "SUCCESS")
return true;
else
return false;
}
catch (Exception ex)
{
throw ex;
}
finally
{
_conOracle.Close();
}
procedure
create or replace
PROCEDURE SERVICE_STATUS( panumber number, pa_link varchar2 default NULL, po_msg OUT VARCHAR2 )
is
BEGIN
--logic comes here
END;
Whenever you have a procedure with one OUT parameter I would rather prefer to create a function instead.
Anyway, looks like you cannot change that, so take what you have.
Try to add the parameter like this:
cmd.Parameters.Add("PO_MSG", OracleDbType.Varchar2, 4000, null, ParameterDirection.Output);
cmd.Parameters["PO_MSG"].DbType = DbType.String;
(Only relevant for older version of ODP.NET providers)
The cmd.ExecuteScalar(); seems to be wrong. See documentation:
This method executes the query using the connection, and returns the
first column of the first row in the result set returned by the query.
You don't execute a query, you want to invoke a procedure. Use cmd.ExecuteNonQuery();
But the real issue should be the size of your output parameter. Apparently 4000 characters is not sufficient. As opposed to SQL (unless you set MAX_STRING_SIZE = EXTENDED) the max. size of VARCHAR2 datatype is 32767, see PL/SQL Program Limits.
So, change your parameter to
cmd.Parameters.Add("PO_MSG", OracleDbType.Varchar2, 32767).Direction = ParameterDirection.Output;

#args is not a parameter for procedure

I am trying to call a stored procedure with a string as parameter (VARCHAR (MAX)) but again and again it tells my #args parameter is not when it certainly is. This is my test procedure:
IF OBJECT_ID ( 'TEST', 'P' ) IS NOT NULL
DROP PROCEDURE TEST;
GO
CREATE PROCEDURE TEST (#args varchar (max)) AS
BEGIN
EXEC sp_execute_external_script
#language = N'R'
, #script = N'OutputDataSet <- as.data.frame(...);'
, #params = N'#args varchar(max)'
, #args = #args
WITH RESULT SETS ((...));
RETURN 0;
END
If I call it from management studio, it works:
SET LANGUAGE ENGLISH
EXEC dbo.TEST #args = 'long string'
GO
but not through C#
public static void Main()
{
Console.WriteLine("Connection test!");
Console.WriteLine("Press ESC to stop");
string ConnectionString = "...";
SqlConnection conn = new SqlConnection(ConnectionString);
SqlCommand cmd = new SqlCommand("TEST");
SqlDataReader rdr = null;
string args = "very long string";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = conn;
cmd.Parameters.Add("#args", SqlDbType.VarChar, -1).Value = args;
conn.Open();
var returnParameter = cmd.Parameters.Add("#ReturnVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
try { cmd.ExecuteNonQuery(); } // #args is not a parameter for TEST Procedure
catch (SqlException ex)
I am not reusing any parameter which is just a varchar(max). Any ideas?
Finally I found the error which was extremely silly.
Short answer: added the SQL USE statement before dropping and creating the proc.
USE myDB;
GO
Long answer: It turns out I have 2 DBs and I was creating the SP in master but I had another procedure in my testing DB. So although I deleted the SP, there was another one in the other DB with the same name but different parameters, hence the error. As I could not understand why #args was incorrect, I listed the SP params (https://stackoverflow.com/a/3038470/2846161, https://stackoverflow.com/a/3038530/2846161) and it turned out that the procedure was listed even being deleted, therefore it was replicated.

Returning a message back from SQL Server Stored Procedure to C# BackgroundWorker

I am using a bacgroundworker in my C# Winforms app to call a stored procedure in SQL Server. The reason I am doing this is that I am using raiserror messages to send back rows counts and messages to a progress bar that shows the progress of the stored procedure. That all works fine. My problem is at the end of the stored procedure I have a message that returns a success message. The success message is declared an an output parameter in the stored procedure.
DECLARE #returnMessage OUTPUT
Then I say something like:
SET #returnMessage = "Posting dues has successfully completed on ' + GetDate()
Now in my app, I have my DoWork method where I connect and execute my stored procedure. Here is the pertinent code:
conn.InfoMessage += (o, args) => self.ReportProgress(0, args.Message);
SqlCommand cmd = new SqlCommand("ua_sp_PostPeriodicDues", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
cmd.Parameters.Add(new SqlParameter("#periodCode", periodCode));
cmd.Parameters.Add(new SqlParameter("#nextPostingDate", nextPostingDate));
cmd.Parameters.Add(new SqlParameter("#repost", repost));
cmd.Parameters.Add(new SqlParameter("#localFieldName", localFieldName));
cmd.Parameters.Add(new SqlParameter("#userCd", userCd));
cmd.Parameters.Add(new SqlParameter("#runNow", runNow));
cmd.Parameters.Add(new SqlParameter("#returnMessage", returnMessage)).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
returnMessage = cmd.Parameters["#returnMessage"].Value.ToString();
returnMessage is a string that is defined at the class level so it is available to the RunWorkerCompleted method.
In my RunWorkerCompleted method I have the following lines.
form.Kill(); //closes progress bar modeless dialog
Cursor.Current = Cursors.Default;
MessageBox.Show(returnMessage); //display the success
Problem is the returnMessage variable always returns an empty string. I am just using an output parameter in the stored procedure with no return. Does my output parameter have to be handled differently on the C# side because it is in a backgroundworker? Is there a better way to return back a success at the end of the stored procedure. Is doing with a backgroundworker causing the problem?
I would break it down and add the Output Paramter and declare the datatype as well as follows:
SqlParameter returnMessage = new SqlParameter("#returnMessage", SqlDbType.String);
returnMessage.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(returnMessage);
cmd.Open();
cmd.ExecuteNonQuery();
var result = returnParameter.Value;
-Please change this code
SET #returnMessage = 'Posting dues has successfully completed on ' + GetDate()
to
SET #returnMessage = 'Posting dues has successfully completed on ' + GetDate()
DECLARE #returnMessage VARCHAR(100) OUTPUT
is not valid TSQL. This should return an error.
OUTPUT parameters have to be actual parameters of the stored procedure. You can't declare them inside the procedure scope and try to return them from there.
Make the output parameter part of the SP definition and it should work.
You say it's working in the SQL Server query analyzer, but not in (I assume) production. The likely culprit is a schema issue. You are referencing your stored procedure without schema-qualifying the name. Reference to SQL objects that are not schame-qualified are looked up in the following manner:
First the current connection's default schema is probed for an object matching the referenced name. If found, the reference is resolved. Otherwise...
The dbo schema is probed for an object matching the referenced name.
It is possible to have multiple objects of the same name that are owned by different schemas, with the result that different logins (attached to different default schemas) can (and will) resolve such unqualified references differently. With the odd results you seem to be seeing.
Unless you have a very good reason not to do so, always schema-qualify your object references and SQL create statements.
That being said, given this stored procedure:
create procedure dbo.mySproc
#p1 varchar(32) ,
#p2 varchar(8000) output
as
set #p2 = case
when #p1 is null then 'Hello, <null>!'
else 'Hello, ' + #p1
end
return 0
go
This code should do you:
using ( SqlConnection connection = new SqlConnection(connectString) )
using( SqlCommand cmd = connection.CreateCommand() )
{
cmd.CommandText = "dbo.mySproc" ;
cmd.CommandType = CommandType.StoredProcedure ;
cmd.Parameters.AddWithValue( "#p1" , "Emily" ) ;
cmd.Parameters.Add( "#p2" , SqlDbType.VarChar , 8000 );
cmd.Parameters["#p2"].Direction = ParameterDirection.Output ;
connection.Open();
int rc = cmd.ExecuteNonQuery();
connection.Close();
string message = (string) cmd.Parameters["#p2"].Value ;
Console.WriteLine( "The message is: {0}",message);
}
And should produce
The message is: Hello, Emily

Procedure or function 'usp_StoredProcName' expects parameter '#inputVal', which was not supplied

I am using a code to call a Stored Procedure having 2 output and 1 input parameter. But i keep getting an error every time I call this stored proc:
CREATE PROCEDURE [dbo].[usp_StoredProcName]
#inputVal nvarchar(255),
#isError bit OUTPUT,
#errorInfo nvarchar(255) OUTPUT
AS BEGIN
DECLARE #totalRow int = 0;
DECLARE #inputValID uniqueidentifier;
SET #isError = 1;
SET #errorInfo = '';
SELECT #inputValID = [inputValID]
FROM testTable
WHERE inputVal = #inputVal;
IF #inputValID IS NULL
BEGIN
SET #isError = 0;
SET #errorInfo = 'inputVal not found';
RETURN
END
END
I have used couple of C# methods to call the stored proc and I get they all return this error:
Procedure or function 'usp_StoredProcName' expects parameter '#inputVal', which was not supplied.
C# Method 1 (to call the stored proc)
using (SqlConnection con = new SqlConnection(myFullConncectionStringToDB))
{
using (SqlCommand cmd = new SqlCommand("usp_StoredProcName", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#inputVal", "MyParamVal_12345");
cmd.Parameters["#isError"].Direction = ParameterDirection.Output;
cmd.Parameters["#errorInfo"].Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
var isError = cmd.Parameters["#isError"].Value;
var errInfo = cmd.Parameters["#errorInfo"].Value;
con.Close();
}
}
Method 2 ( to call the stored proc)
SqlConnection con = new SqlConnection(myFullConncectionStringToDB);
SqlCommand cmd = new SqlCommand("usp_StoredProcName", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter in_parm = new SqlParameter("#inputVal", SqlDbType.NVarChar);
in_parm.Size = 255;
in_parm.Value = "MyParamVal_12345";
in_parm.Direction = ParameterDirection.Input;
cmd.Parameters.Add(in_parm);
SqlParameter out_parm = new SqlParameter("#errorInfo", SqlDbType.NVarChar);
out_parm.Size = 255;
out_parm.Direction = ParameterDirection.Output;
cmd.Parameters.Add(out_parm);
SqlParameter out_parm1 = new SqlParameter("#isError", SqlDbType.Bit);
out_parm1.Direction = ParameterDirection.Output;
cmd.Parameters.Add(out_parm1);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
Both of the above methods I tried return the same error:
Procedure or function 'usp_StoredProcName' expects parameter '#inputVal', which was not supplied.
Please tell me what am I doing wrong here in my C# code to execute the stored procedure.
I am clearly passing the parameter value in both of my methods but can't figure out why I keep getting this error.
Thank you for your help.
I usually break down the solution into pieces an make sure each one works.
First, test the Stored Procedure to make sure it works as planned. Sample call is below.
-- Switch to your database
USE [YourDatabase]
GO
-- Declare output variables
DECLARE #out_is_error bit;
DECLARE #out_error_info nvarchar(255);
-- Execute sp
EXECUTE [dbo].[usp_StoredProcName]
N'In Data',
#isError = #out_is_error OUTPUT,
#errorInfo = #out_error_info OUTPUT;
-- Show any SQL errors / return data
PRINT ##ERROR;
PRINT 'Error = ' + #out_error_info;
PRINT 'Flag = ';
PRINT CAST(#out_is_error as CHAR(1));
GO
Next, look at the C# piece of the puzzle. Aaron suggestion about correct database is a good one. Do you have two copies of the SP floating around?
Good luck.

Must a T-Sql stored procedure contain script to support a SqlClient transaction?

I have a stored procedure that deletes rows. Sample code:
CREATE PROCEDURE [dbo].[ap_um_delete_tems_grid]
(
#agency char(3)
, #subagency char(1)
, #grid_id int
, #role_id int
)
AS
DELETE FROM [grid_setup]
WHERE agency = #agency
AND subagency = #subagency
AND gs.grid_id = #grid_id
AND role_id = #role_id
If I execute this SProc directly from Sql Mgmt Studio it works fine. However, if I attempt to do it in C# code using a transaction, I get a very interesting SqlException:
Incorrect syntax near 'ap_um_delete_tems_grid'
The exception detail says it occurs on line number 1. The C# code is:
using (SqlConnection connection = new SqlConnection(conn.TemsConnectionString))
{
connection.Open();
SqlCommand command = connection.CreateCommand();
SqlTransaction transaction;
// Start the local transaction
transaction = connection.BeginTransaction("GridReplaceTransaction");
command.Connection = connection;
command.Transaction = transaction;
try
{
command.CommandText = "ap_um_delete_tems_grid";
SqlParameter parm = new SqlParameter();
// Adding the parameters
int cnt = command.ExecuteNonQuery();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
}
}
The code above worked before I put it into a transaction. Why am I getting the syntax error? Perhaps because there needs to be something in the SProc to support the transaction? Or am I messsing something else up?
NOTE: Please don't try to tell me I don't need a transaction for a single delete. The above is part of a multi-step process, namely adding new rows after the delete. Thanks.
You are missing:
command.CommandType = CommandType.StoredProcedure;
Otherwise, it uses the default of CommandType.Text and treats "ap_um_delete_tems_grid" as a statement rather than the name of a stored procedure.

Categories

Resources