Invalid length parameter passed to LEFT or SUBSTRING function - c#

I got this error mess "Invalid length parameter passed to LEFT or SUBSTRING function" from this below. Anyone can give me a hint what cause this, and how I can solve it?
string cmdText = #"Declare #SqlString nvarchar(2500)
, #AreaDelimiter char(1)
, #AreaFilter nvarchar(max);
Select #AreaDelimiter = ','
If (#AreaName Not Like '*')
Begin
Set #AreaName = #AreaName + #AreaDelimiter
Set #AreaFilter = ''
While LEN(#AreaName) > 0
Begin
If (Len(#AreaFilter) > 0)
Begin
Set #AreaFilter = #AreaFilter + ' Or Area Like ''' +
LTRIM(SubString(#AreaName, 1,
CharIndex(#AreaDelimiter, #AreaName) - 1)) + '%'''
End
Else
Begin
Set #AreaFilter = 'Area Like ''' +
LTRIM(SubString(#AreaName, 1,
CharIndex(#AreaDelimiter, #AreaName) - 1)) + '%'''
End
Select #AreaName = SUBSTRING(#AreaName, CharIndex(#AreaDelimiter,
#AreaName) + 1, Len(#AreaName))
End
End"
this code above continues with the else statement and the others operations who works :)
And this is my C# code:
string area = "AREA1,AREA2,AREA3";
using (SqlConnection conn = new SqlConnection(domain.getDecryptedSqlConnectionString(domain.name + passPhrase)))
{
using (SqlCommand cmd = new SqlCommand(cmdText, conn))
{
System.Globalization.CultureInfo cInfo = new System.Globalization.CultureInfo("pt-BR");
DateTime dt = DateTime.Parse(startDate, cInfo);
DateTime da = DateTime.Parse(endDate, cInfo);
cmd.Parameters.Add("Interval", SqlDbType.Int).Value = interval;
cmd.Parameters.Add("IntervalUnit", SqlDbType.VarChar).Value = intervalUnit;
cmd.Parameters.Add("StartDate", SqlDbType.DateTime).Value = dt.ToShortDateString();
cmd.Parameters.Add("EndDate", SqlDbType.DateTime).Value = da.ToShortDateString();
cmd.Parameters.Add("tbName", SqlDbType.VarChar).Value = domain.alarmTableName;
cmd.Parameters.Add("AreaName", SqlDbType.VarChar).Value = area;
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
using (DataTable tb = new DataTable())
{
try
{
conn.Open();
adapter.Fill(tb);
return tb;
}
catch (Exception ex)
{
return tb;
}
finally
{
conn.Close();
}
}
}
}
}
SOLVED, I JUST CHANGE
cmd.Parameters.Add("AreaName", SqlDbType.VarChar).Value = area;
FOR
cmd.Parameters.Add("AreaName", SqlDbType.VarChar, -1).Value = area;

I can reproduce the error with
DECLARE #AreaName VARCHAR(20);
DECLARE #AreaDelimiter CHAR(1);
DECLARE #AreaFilter VARCHAR(100);
SET #AreaName='AREA1,AREA2,AREA3,area4,area5';
SET #AreaDelimiter=',';
Notice that the declaration of #AreaName is not long enough for the data - check your declaration.
Also, if the string for #AreaName has come from user input, your code is vulnerable to SQL injection attacks.
EDIT:
All your SQL parameter names need to start with #, e.g. #AreaName, and you must match up the SqlDbType between your C# code and the SQL code.
You shouldn't be using
cmd.Parameters.Add("StartDate", SqlDbType.DateTime).Value = dt.ToShortDateString();
instead it should be
cmd.Parameters.Add("StartDate", SqlDbType.DateTime).Value = dt;
because dt is already a DateTime.

Related

How to call plpgsql function from c#

I've created a function in plpgsql and I'm trying to call the stored procedure from .net core api
But I'm getting following exception in c#
42883: function proc_insert_test(brndcode => integer, brndname => character varying, brndsname => character varying, prdtype => character, discontinue => character, crddate => date, status => integer, recstat => integer, brndgrpseqno => integer, wefrom => date) does not exist
No function matches the given name and argument types. You might need to add explicit type casts.
Procedure:
CREATE OR REPLACE FUNCTION public.proc_insert_test(p_brndcode integer,
p_brndname varchar(100),
p_brndsname varchar(100),
p_prdtype char(1),
p_discontinue char(1),
p_crddate date,
p_status integer,
p_recstat integer,
p_brndgrpseqno integer,
p_wefrom date)
RETURNS char
LANGUAGE plpgsql
AS $body$
BEGIN
Insert into arc_mmstbrndgroup(brndcode, brndname, brndsname, prdtype, discontinue, crddate, status, recstat, brndgrpseqno, wefrom)
values(p_brndcode, p_brndname, p_brndsname, p_prdtype, p_discontinue, p_crddate, p_status, p_recstat, p_brndgrpseqno, p_wefrom);
return 'saved';
END;
$body$
;
Procedure calling from c#:
NpgsqlCommand cmd = new NpgsqlCommand("proc_insert_test", _connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#brndcode", NpgsqlTypes.NpgsqlDbType.Integer, 123);
cmd.Parameters.AddWithValue("#brndname", NpgsqlTypes.NpgsqlDbType.Varchar, 100, "Test3");
cmd.Parameters.AddWithValue("#brndsname", NpgsqlTypes.NpgsqlDbType.Varchar, 100, "Test3");
cmd.Parameters.AddWithValue("#prdtype", NpgsqlTypes.NpgsqlDbType.Char, 1, "T");
cmd.Parameters.AddWithValue("#discontinue", NpgsqlTypes.NpgsqlDbType.Char, 1, "T");
cmd.Parameters.AddWithValue("#crddate", NpgsqlTypes.NpgsqlDbType.Date, DateTime.Now);
cmd.Parameters.AddWithValue("#status", NpgsqlTypes.NpgsqlDbType.Integer, 1);
cmd.Parameters.AddWithValue("#recstat", NpgsqlTypes.NpgsqlDbType.Integer, 9);
cmd.Parameters.AddWithValue("#brndgrpseqno", NpgsqlTypes.NpgsqlDbType.Integer, 1234);
cmd.Parameters.AddWithValue("#wefrom", NpgsqlTypes.NpgsqlDbType.Date, DateTime.Now);
_connection.Open();
cmd.ExecuteNonQuery();
cmd.Dispose();
_connection.Close();
What can be the issue?
I'm also faced this issue. After some analyze found that date datatype casting not working. So we changed our calling method like this,
Without return value:
string strquery = "SELECT PROC_INSERT_TEST(123,'Test3','Test3','T','T',";
strquery = strquery + "'" + DateTime.Now.ToString("MMM-dd-yyyy HH:mm:ss") + "',1,9,1234,";
strquery = strquery + "'" + DateTime.Now.ToString("MMM-dd-yyyy HH:mm:ss") + "')";
NpgsqlCommand cmd = new NpgsqlCommand(strquery, _connection);
_connection.Open();
cmd.ExecuteNonQuery();
cmd.Dispose();
_connection.Close();
With return value
string strquery = "BEGIN; SELECT PROC_INSERT_TEST_WITH_RETURN(123,'Test3','Test3','T','T',";
strquery = strquery + "'" + DateTime.Now.ToString("MMM-dd-yyyy HH:mm:ss") + "',1,9,1234,";
strquery = strquery + "'" + DateTime.Now.ToString("MMM-dd-yyyy HH:mm:ss") + "')";
NpgsqlCommand cmd = new NpgsqlCommand(strquery, _connection);
_connection.Open();
object cursorVal = cmd.ExecuteScalar();
DataSet ds = FetchAll(_connection, cursorVal);
cmd.Dispose();
_connection.Close();
private DataSet FetchAll(NpgsqlConnection _connection, object cursorVal)
{
try
{
DataSet actualData = new DataSet();
string strSql = "fetch all from \"" + cursorVal + "\";";
NpgsqlCommand cmd = new NpgsqlCommand(strSql, _connection);
NpgsqlDataAdapter ada = new NpgsqlDataAdapter(cmd);
ada.Fill(actualData);
return actualData;
}
catch (Exception Exp)
{
throw new Exception(Exp.Message);
}
}
For me It is working
PGDbContext _context = new PGDbContext();
string d1 = "mm5";
string d2 = "mmTest6";
int d3 = 11;
string d4 = "1";
var DistributionChannelGUID = _context.Database.SqlQuery<List<string>>("call dbo.insupdelglclassmaster({0},{1},{2},{3})", d1, d2, d3, d4).ToList();
if function have
Param1 character varying DEFAULT array[]::character varying[]
then how to skip to pass from c#.

DataTable Is Empty

I am attempting to run a stored procedure and add the results to a data table. My stored procedure executes as it should, bc if I query the table the results are stored in from SSMS - the accurate results are there. However, my code below will produce numberofrecords = 0 everytime!
What did I set-up incorrectly in this syntax below?
using (conn = new SqlConnection(SQLConn))
{
using (cmd = new SqlCommand(storedprocname, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Name", SqlDbType.VarChar, 100);
cmd.Parameters.Add("d1", SqlDbType.Date, 100);
cmd.Parameters.Add("d2", SqlDbType.Date, 100);
cmd.Parameters["#Name"].Value = cboNames.Text.ToString();
cmd.Parameters["d1"].Value = dtpd1.Value.ToString("MM/dd/yyyy");
cmd.Parameters["d2"].Value = dtpd2.Value.ToString("MM/dd/yyyy");
cmd.Parameters.Add("#Dolla", SqlDbType.VarChar, 100);
cmd.Parameters["#Dolla"].Value = cboDolla.Text.ToString();
using (da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
int numberOfRecords = 0;
numberOfRecords = dt.Select().Length;
MessageBox.Show(numberOfRecords.ToString());
}
And these are my class variable declarations:
public static SqlCommand cmd;
public static SqlDataAdapter da;
public static DataSet ds = new DataSet();
public static DataTable dt = new DataTable();
EDIT
And this is my stored proc which produces roughly 32 rows
ALTER Procedure [dbo].[TestParamQuery]
(
#Name varchar(max)
,#d1 varchar(100)
,#d2 varchar(100)
,#dolla varchar(500)
)
As
Select
EmployeeName
,EmployeeNumber
,CAST(hiredate As Date) [hire date]
,saleamount
FROM [TestDB].[dbo].[SalesFigs]
WHERE employeename = #Name
AND hiredate between #d1 AND #d2
AND saleamount >= #dolla
EDIT 2
This is how I execute the stored procedure to ensure it is returning the results I want from directly inside SSMS
USE [TestDB]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[TestParamQuery]
#Name = N'Sam Wise',
#d1 = N'03/01/2016',
#d2 = N'01/30/2016',
#Dolla = N'1000'
SELECT 'Return Value' = #return_value
GO
Unfortunately, SqlCommand does not have an easy method or property for converting the command to a string, with all parameters and values included. I have used a method like this in the past to make debugging commands easier:
public static string PrintCommand(this SqlCommand command){
if (command == null) throw new ArgumentNullException("command");
var sb = new StringBuilder();
sb.AppendLine(command.CommandText);
foreach (var p in command.Parameters){
sb.AppendLine("\t" + p.ParameterName + ": " + p.Value);
}
return sb.ToString();
}
It should output a string like this:
"dbo.MyCommandName
#Name: myNameParameterValue
d1: 01/01/2016
d2: 02/02/2016
#Dolla: myDollaValue"
You can then invoke it like this, and check the value in a step-thru debugger.
using (conn = new SqlConnection(SQLConn))
using (cmd = new SqlCommand(storedprocname, conn)) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Name", SqlDbType.VarChar, 100);
cmd.Parameters.Add("d1", SqlDbType.Date, 100);
cmd.Parameters.Add("d2", SqlDbType.Date, 100);
cmd.Parameters["#Name"].Value = cboNames.Text.ToString();
cmd.Parameters["d1"].Value = dtpd1.Value.ToString("MM/dd/yyyy");
cmd.Parameters["d2"].Value = dtpd2.Value.ToString("MM/dd/yyyy");
cmd.Parameters.Add("#Dolla", SqlDbType.VarChar, 100);
cmd.Parameters["#Dolla"].Value = cboDolla.Text.ToString();
//Get a text representation here:
var text = cmd.PrintCommand();
//Put a breakpoint here to check the value:
using (da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
int numberOfRecords = 0;
numberOfRecords = dt.Select().Length;
MessageBox.Show(numberOfRecords.ToString());
}
Not sure why you cannot get values. But anyway please try this approach:
using (conn = new SqlConnection(SQLConn))
using (cmd = new SqlCommand(storedprocname, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Name", cboNames.Text);
cmd.Parameters.AddWithValue("d1", dtpd1.Value.ToShortDateString();
cmd.Parameters.AddWithValue("d2", dtpd2.Value.ToShortDateString();
cmd.Parameters.AddWithValue("#Dolla", cboDolla.Text);
using (da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
var numberOfRecords = dt.Rows.Count;
MessageBox.Show(numberOfRecords);
}

ODP.Net Managed API - Array Binding with strings > 1000 characters

When using the ODP.Net managed API, when using array binding to insert data into a column of type VARCHAR2(4000), and a string length of a row value in our array is greater than 1000 characters, the following exception is thrown:
ORA-01461: can bind a LONG value only for insert into a LONG column
string sql = "INSERT INTO STAGING(\"COLUMN1\") VALUES (:COLUMN1)";
using (OracleCommand cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
cmd.BindByName = true;
cmd.ArrayBindCount = dt.Rows.Count;
var p = new OracleParameter { ParameterName = parameterName.ToUpper() };
p.OracleDbType = OracleDbType.Varchar2;
p.Value = dt.AsEnumerable().Select(c => (!c.IsNull(fieldName) ? c.Field<T>(fieldName) : default(T))).ToArray();
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
}
We currently define our parameters as:
p.OracleDbType = OracleDbType.Varchar2;
I tried to use this instead, but still run into the same issue:
p.OracleDbType = OracleDbType.Clob;
Also tried to set a size on the length of the Varchar2 as follows, but still have the same issue.
p.OracleDbType = OracleDbType.Varchar2;
p.Size = 4000;
Also tried this, with no luck:
string sql = "INSERT INTO STAGING(\"COLUMN1\") VALUES (CAST(:COLUMN1 AS VARCHAR2(4000))";
Any ideas?
This appears to be a similiar issue: https://community.oracle.com/thread/3649551
Update
I suspected that maybe there was some sort of character set issue, which made the length longer than expected, so to rule this out, I reduced the column length of the table that we're trying to insert data into down to VARCHAR2(1000), assuming that this would make the maximum allowable character length to be 250 - this is not the case though. The maximum that is working before this exception is thrown is still 1000.
Update 2
I've found an oracle patch which may resolve this issue. I will try and get this patch and verify. https://support.oracle.com/epmos/faces/PatchDetail?patchId=20361140&requestId=18735492
Update 3
The oracle patch didn't fix the issue for me. I tried to iterate through all of the parameter bind statuses, but they all indicate a success.
catch (Exception ex)
{
foreach (OracleParameter p in cmd.Parameters)
{
foreach (var s in p.ArrayBindStatus)
{
if (s != OracleParameterStatus.Success)
{
}
}
}
}
Update 4
Seems that this is a bug in the Oracle Managed API, here's a sample class that can reproduce the issue.
namespace OracleBindError
{
using Oracle.ManagedDataAccess.Client;
using System.Data;
using System.Linq;
class Program
{
static void Main(string[] args)
{
string testTable = "BIND_TEST_TABLE";
string connString = "[conn string here]";
string dropTable =
#"DECLARE pEXISTS NUMBER;
BEGIN
SELECT COUNT(*) INTO pEXISTS FROM USER_TABLES WHERE TABLE_NAME = '" + testTable + #"';
IF(pEXISTS > 0) THEN
EXECUTE IMMEDIATE 'DROP TABLE " + testTable + #"';
END IF;
EXECUTE IMMEDIATE 'CREATE TABLE " + testTable + #" (COLUMN1 VARCHAR2(4000), COLUMN2 VARCHAR2(4000))';
END;";
string[] greaterThanOneThousand = new string[] {
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkldfdffd",
};
string insertStatement = "INSERT INTO " + testTable + "(\"COLUMN1\",\"COLUMN2\") VALUES (:COLUMN1,:COLUMN2)";
using (OracleConnection conn = new OracleConnection(connString))
{
conn.Open();
OracleCommand dropCmd = new OracleCommand(dropTable, conn);
dropCmd.ExecuteNonQuery();
using (OracleCommand cmd = conn.CreateCommand())
{
cmd.CommandText = insertStatement;
cmd.CommandType = CommandType.Text;
cmd.BindByName = true;
cmd.ArrayBindCount = greaterThanOneThousand.Length;
var p = new OracleParameter { ParameterName = "COLUMN1" };
p.OracleDbType = OracleDbType.Varchar2;
p.Value = greaterThanOneThousand.ToArray();
cmd.Parameters.Add(p);
var p2 = new OracleParameter { ParameterName = "COLUMN2" };
p2.OracleDbType = OracleDbType.Varchar2;
p2.Value = new string[] { null };
cmd.Parameters.Add(p2);
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
}
}
Found work-around
If I change the OracleDbType from Varchar2 to NVarchar2 in my parameters it works.
var p = new OracleParameter { ParameterName = "COLUMN1" };
p.OracleDbType = OracleDbType.NVarchar2;
p.Value = greaterThanOneThousand.ToArray();
cmd.Parameters.Add(p);
var p2 = new OracleParameter { ParameterName = "COLUMN2" };
p2.OracleDbType = OracleDbType.Varchar2;
p2.Value = new string[] { " " };
cmd.Parameters.Add(p2);
Work-Around
The work-around is to use NVARCHAR2 in the parameter on the .net side.
You are assigning array of type "T" into value. Whereas, the database expects it to be VARCHAR2(4000), which is equivalent to string. Try converting the value to string.

Call oracle stored function

I try to call my oracle function, but for some reason i get wiered results from it.
This is my C# code :
using (OracleConnection _conn = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.20.190.2)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=DBIDB)));User Id=blng;Password=blng;"))
{
using (OracleCommand cmd = new OracleCommand())
{
_conn.Open();
cmd.Connection = _conn;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "PKG_update_switch.checkexistsinswitch";
cmd.Parameters.Add("phone", OracleDbType.Varchar2, ParameterDirection.Input).Value = phoneToQuery;
cmd.Parameters.Add("res", OracleDbType.Int32, ParameterDirection.ReturnValue);
cmd.ExecuteNonQuery();
result = cmd.Parameters["res"].Value.ToString();
Debug.WriteLine("---" + result);
if (result.Equals("null"))
message = "Didnt find number";
else
message = "Found " + phoneToQuery + " in " + result;
MessageBox.Show(message, "Check Phone Exists",
MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk);
_conn.Close();
}
}
As a result i always get 0, witch is imposible.
Oracle function:
function checkExistsInSwitch(phone in varchar2) RETURN integer is
tmp varchar2(100):='';
begin
for t in (select c.re_collection_id from re_collection_values c where c.start_range = phone)
loop
----- check that the number is from folder number 2
begin
select o.network_identifier into tmp from operators o where o.switch_folder_id = t.re_collection_id;
return 11;--tmp;
exception
when others then
null;
end;
end loop;
return 11;--'';
end;
this is very wiered, for a stored procedure i get good results, this only happend to my with the stored functions.

How to get the return value and rows in c# thru stored procedure

In the below Stored procedure, i am returning a row if all the conditions satisfies, orelse i am returning a message like which condition is nor satisfied.
The Stored proc is working perfectly...
ALTER PROCEDURE dbo.BookingCheck
(
#int_duration_of_stay int ,
#int_number_of_guests int,
#date_of_application date,
#date_of_checkin date,
#date_of_checkout date,
#str_room_type varchar(50),
#ret_value varchar(100) = '' output
)
AS
DECLARE #MaxPer int
DECLARE #BasicCharge int
DECLARE #SurCharge int
DECLARE #TotalAmount int
DECLARE #NoOfDays int
DECLARE #Free VARCHAR(10)
IF #int_duration_of_stay > 6
BEGIN
SET #NoOfDays = #int_duration_of_stay
SET #Free = 'Yes'
END
ELSE
BEGIN
SET #NoOfDays = #int_duration_of_stay - 1
SET #Free = 'No'
END
SELECT #MaxPer = int_max_pax, #BasicCharge = flt_basic_charge, #SurCharge = flt_surcharge_per_pax
FROM RoomTypes WHERE UPPER(str_room_type) = UPPER(#str_room_type)
IF DATEDIFF(DAY, GETDATE(), #date_of_checkin) < 40
BEGIN
IF #int_number_of_guests <= #MaxPer
BEGIN
SET #TotalAmount = (#NoOfDays * #int_number_of_guests * #SurCharge) + #BasicCharge
SET #ret_value = 'Success'
SELECT #str_room_type as 'Room Type', #MaxPer as 'Max Persons Allowed', #int_number_of_guests as 'No. of persons requested',
#int_duration_of_stay as 'No. of days stay', #BasicCharge as 'Basic Charge', #SurCharge as 'Sur Charge', #Free as 'Complimentary',
#TotalAmount as 'Total Amount'
END
ELSE
BEGIN
SET #ret_value = 'Max persons allowed is ' + CONVERT(VARCHAR(20), #MaxPer)
END
END
ELSE
BEGIN
SET #ret_value = 'The check in date should be less than 40 days from current date.'
END
RETURN
The problem is dont know how to get the return message or return row from the SP using c#.
The below code returns me the rows if the condition is satisfied in SP. if not, i am not getting the return message. How to get that ?
public DataSet BookingCheck(int duration_of_stay, int number_of_guests,
string date_of_application, string date_of_checkin, string date_of_checkout,
string room_type)
{
DataSet dsGetBookingCheck = new DataSet();
SqlConnection conn = new SqlConnection(Con);
SqlCommand command = new SqlCommand("BookingCheck", conn);
command.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter();
SqlParameter param = new SqlParameter();
param = command.Parameters.Add("#int_duration_of_stay", SqlDbType.Int);
param.Value = duration_of_stay;
param = command.Parameters.Add("#int_number_of_guests", SqlDbType.Int);
param.Value = number_of_guests;
param = command.Parameters.Add("#date_of_application", SqlDbType.Date);
param.Value = date_of_application;
param = command.Parameters.Add("#date_of_checkin", SqlDbType.Date);
param.Value = date_of_checkin;
param = command.Parameters.Add("#date_of_checkout", SqlDbType.Date);
param.Value = date_of_checkout;
param = command.Parameters.Add("#str_room_type", SqlDbType.VarChar, 50);
param.Value = room_type;
conn.Open();
command.ExecuteNonQuery();
da.SelectCommand = command;
da.Fill(dsGetBookingCheck);
conn.Close();
return dsGetBookingCheck;
}
You need to add an out parameter:
command.Parameters.Add("#ret_value", SqlDbType.String);
command.Parameters["#ret_value"].Direction = ParameterDirection.Output;
then after executing the SP
message = command.Parameters["#ret_value"].Value.ToString();
Here is function with out param:
public DataSet BookingCheck(int duration_of_stay, int number_of_guests,
string date_of_application, string date_of_checkin, string date_of_checkout,
string room_type, out string message)
{
DataSet dsGetBookingCheck = new DataSet();
SqlConnection conn = new SqlConnection(Con);
SqlCommand command = new SqlCommand("BookingCheck", conn);
command.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter();
SqlParameter param = new SqlParameter();
param = command.Parameters.Add("#int_duration_of_stay", SqlDbType.Int);
param.Value = duration_of_stay;
param = command.Parameters.Add("#int_number_of_guests", SqlDbType.Int);
param.Value = number_of_guests;
param = command.Parameters.Add("#date_of_application", SqlDbType.Date);
param.Value = date_of_application;
param = command.Parameters.Add("#date_of_checkin", SqlDbType.Date);
param.Value = date_of_checkin;
param = command.Parameters.Add("#date_of_checkout", SqlDbType.Date);
param.Value = date_of_checkout;
param = command.Parameters.Add("#str_room_type", SqlDbType.VarChar, 50);
param.Value = room_type;
command.Parameters.Add("#ret_value", SqlDbType.String);
command.Parameters["#ret_value"].Direction = ParameterDirection.Output;
conn.Open();
command.ExecuteNonQuery();
da.SelectCommand = command;
da.Fill(dsGetBookingCheck);
message = command.Parameters["#ret_value"].Value.ToString();
conn.Close();
return dsGetBookingCheck;
}
NOTE: I have never done with with using ExecuteNonQuery and then using Fill on a data adapter. That might mess this up.
What is ExecuteNonQuery doing in your code when you are not inserting anything?
There are ways to do this. One, use a DataReader. It is a bit more helpful in these kind of scenarios. Or you can add a output parameter to the stored procedure and check that after you execute the proc through C#.
That's not doable in C#. You can only either return a DataTable with a single row (using the Fill method in your example) or you can return a single value (using an SqlCommand with a return parameter or ExecuteScalar).
Instead you should do a SELECT in both cases but with different fields depending on the IF statement. I.e.,
SET #ret_value = 'Max persons allowed is ' + CONVERT(VARCHAR(20), #MaxPer)
is converted to be
SELECT 'Max persons allowed is ' + CONVERT(VARCHAR(20), #MaxPer) AS Return_Value
And then you check for the field name in your return DataTable. E.g.
if (BookingCheck(...).Tables[0].Columns.Contains("Return_Value")) {
// Handle my special condition here
}

Categories