Specified cast is not valid when trying Convert.ToInt32(value) - c#

I am trying to run a stored procedure and for some reason it keeps telling me "Specified cast is not valid". the "hidSelectedExpenseIDs" is a hidden field that gets populated with a javascript array of id's.
Example: the "hidSelectedExpenseIDs.Value" would look like "123,124,125,126". Hence why I have the .Split(',') in there.
Here is my code:
public void hasExhistingExpenseInvoice()
{
string[] Expenses = hidSelectedExpenseIDs.Value.Split(',');
//check if there is an existing invoice. Then report back to the user so the
//user knows if he/she has to check overwrite option.
bool invoiceExists = false;
foreach (var expense in Expenses)
{
var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["OSCIDConnectionString"].ToString());
var command = new SqlCommand("p_CaseFiles_Expenses_InvoiceExhists", connection);
command.Parameters.Add(new SqlParameter("#ExpenseID", SqlDbType.Int));
command.Parameters["#ExpenseID"].Value = Convert.ToInt32(expense);
command.CommandType = CommandType.StoredProcedure;
try
{
connection.Open();
invoiceExists = (bool)command.ExecuteScalar();
if (invoiceExists)
{
//previous invoice exhists
Warning1.Visible = true;
Warning1.Text = "There is an exhisting Invoice.";
}
}
catch (SqlException sql)
{
lblStatus.Text = "Couldn't connect to the Database - Error";
lblStatus.ForeColor = System.Drawing.Color.Red;
}
catch (Exception ex)//catches exception here
{
lblStatus.Text = "An error occured";
lblStatus.ForeColor = System.Drawing.Color.Red;
}
finally
{
if (connection.State == ConnectionState.Open)
connection.Close();
}
}
}
this is my stored procedure:
ALTER PROCEDURE dbo.[InvoiceExhists]
#ExpenseID int
AS
BEGIN
SELECT InvNumber FROM dbo.Expenses from ExpID = #ExpenseID
END

The logic is faulty.
Your Query returns a number, and you are trying to cast it directly to a Boolean, this can't be done in C#.
Some languages will interpret any non-zero as true, it is not the case for C# and it will throw an exception.
You will need to compare the returned value.
In this case, you should just check if there is a value, because NULL will be returned if the invoice does not exist.
This would look like this :
invoiceExists = command.ExecuteScalar() != null ;
Also I recommend reading this thread and consider using UDF instead of scalar Stored Procedures.

change your stored procedure .This fits your requirement
ALTER PROCEDURE [dbo].[InvoiceExhists]
#ExpenseID int
AS
BEGIN
if exists(select * Expenses where ExpID = #ExpenseID)
select 1
else
select 0
END

The exception is likely caused by invoiceExists = (bool)command.ExecuteScalar(); considering its the only casting that happens within the try statement. You need to look at the return result of ExecuteScalar() to solve your problem.

Related

Error Converting datatype nvarchar to int from c# to sql

Hi Guys please help me out in my code where I got stuck and went wrong, I have two tables; one employee table and another branch table. The branch id will be stored in employee table which is a foreign key. When I'm inserting the data through stored procedure where I kept the code like bleow
Create procedure [dbo].[Insertemployee]
#d28 int,#d1 nchar(15),#d2 nchar(30),#d3 int,#d4 nchar(10),#d5 nchar(20),#d6 nchar(30),#d7 varchar(100),#d8 nchar(100),#d9 nchar(10),#d10 nchar(10),#d11 nchar(30),#d12 nchar(30),#d13 nchar(30),#d14 nchar(30),#d15 nchar(30),#d16 date,#d17 varchar(100),#d18 int,#d19 int,#d20 int,#d21 int,#d22 int,#d23 int,#d24 int,#d25 image,#d26 date,#d27 date,#d29 nchar(10)
AS
BEGIN
SET NOCOUNT ON
BEGIN TRY
BEGIN TRANSACTION
insert into Employee(Id,StaffID,StaffName,Branchid,Gender,DOB,FatherName,PermanentAddress,Country,PhoneNo,MobileNo,DateOfJoining,VisaNumber,PassportNumber,PassportExpiryDate,NationalityID,NationalityIDExpiryDate,Designation,BasicSalary,CostOfAllowance,HRA,TeaAndSnacks,Bonus,Loan,OtherDeduction,Picture,createddate,lastmodified,Active) VALUES (#d28,#d1,#d2,(select branchid from Branch where Branch.BranchName=#d3),#d4,#d5,#d6,#d7,#d8,#d9,#d10,#d11,#d12,#d13,#d14,#d15,#d16,#d17,#d18,#d19,#d20,#d21,#d22,#d23,#d24,#d25,#d26,#d27,#d29);
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF ##TRANCOUNT >0
BEGIN
ROLLBACK TRANSACTION
END
EXECUTE uspLogError
END CATCH
END;`
and my front end code is below
cmd = new SqlCommand("InsertEmployee");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;
cmd.Parameters.AddWithValue("#d28",txtID.Text);
cmd.Parameters.AddWithValue("#d26", System.DateTime.Now);
cmd.Parameters.AddWithValue("#d27", System.DateTime.Now);
cmd.Parameters.AddWithValue("#d1", txtStaffID.Text);
cmd.Parameters.AddWithValue("#d2",txtStaffName.Text);
cmd.Parameters.AddWithValue("#d3",txtDepartment.Text);
cmd.Parameters.AddWithValue("#d4",cmbGender.Text);
cmd.Parameters.AddWithValue("#d6",txtFatherName.Text);
cmd.Parameters.AddWithValue("#d7",txtPAddress.Text);
cmd.Parameters.AddWithValue("#d8",txtTAddress.Text);
cmd.Parameters.AddWithValue("#d9",txtPhoneNo.Text);
cmd.Parameters.AddWithValue("#d10",txtMobileNo.Text);
cmd.Parameters.AddWithValue("#d11",dtpDateOfJoining.Value);
cmd.Parameters.AddWithValue("#d12",visanumber.Text.Trim());
cmd.Parameters.AddWithValue("#d14",PassportExpirydate.Text);
cmd.Parameters.AddWithValue("#d15",NationalityID.Text.Trim());
if (NationalityID.Text == "")
{
cmd.Parameters.AddWithValue("#d16", "");
}
else
{
cmd.Parameters.AddWithValue("#d16", NationalityExpirydate.Value);
}
cmd.Parameters.AddWithValue("#d17",txtDesignation.Text.Trim());
cmd.Parameters.AddWithValue("#d13",Passportnumber.Text.Trim());
cmd.Parameters.AddWithValue("#d18",Convert.ToInt32(txtBasicSalary.Text.Trim()));
if (txtLIC.Text == "")
{
cmd.Parameters.AddWithValue("#d19", 0);
}
else
{
cmd.Parameters.AddWithValue("#d19",Convert.ToInt32(txtLIC.Text.Trim()));
}
if (txtGrpInsurance.Text == "")
{
cmd.Parameters.AddWithValue("#d21", 0);
}
else
{
cmd.Parameters.AddWithValue("#d21",Convert.ToInt32(txtGrpInsurance.Text.Trim()));
}
if (txtFamilyBenefitFund.Text == "")
{
cmd.Parameters.AddWithValue("#d22",0);
}
else
{
cmd.Parameters.AddWithValue("#d22",Convert.ToInt32(txtFamilyBenefitFund.Text.Trim()));
}
if (txtLoans.Text == "")
{
cmd.Parameters.AddWithValue("#d23",0);
}
else
{
cmd.Parameters.AddWithValue("#d23",Convert.ToInt32(txtLoans.Text.Trim()));
}
if (txtOtherDeductions.Text == "")
{
cmd.Parameters.AddWithValue("#d24",0);
}
else
{
cmd.Parameters.AddWithValue("#d24",Convert.ToInt32(txtOtherDeductions.Text.Trim()));
}
if (txtIncomeTax.Text == "")
{
cmd.Parameters.AddWithValue("#d20",0);
}
else
{
cmd.Parameters.AddWithValue("#d20",Convert.ToInt32(txtIncomeTax.Text.Trim()));
}
cmd.Parameters.AddWithValue("#d29", chkActive.Text);
cmd.Parameters.AddWithValue("#d5",DOB.Text);
MemoryStream ms = new MemoryStream();
Bitmap bmpImage = new Bitmap(pictureBox1.Image);
bmpImage.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] data = ms.GetBuffer();
SqlParameter p = new SqlParameter("#d25", SqlDbType.Image);
p.Value = data;
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
d3 field can accept int but you are passing string`
default type of TextBox is string
you can fix this by converting to int
cmd.Parameters.AddWithValue("#d3",txtDepartment.Text);
to
cmd.Parameters.AddWithValue("#d3",Convert.ToInt(txtDepartment.Text));
You are passing few fields as string to DB datatype int :
cmd.Parameters.AddWithValue("#d28",txtID.Text);
cmd.Parameters.AddWithValue("#d3",txtDepartment.Text);
you should convert them to int prior passing it to db
cmd.Parameters.AddWithValue("#d28",Convert.ToInt32(txtID.Text.Trim()));
cmd.Parameters.AddWithValue("#d3",Convert.ToInt32(txtDepartment.Text.Trim()));
Just curious how come your txtDepartment be type of int , either you have to make a check whether there is string being passed or its an number . If it accepts only number you might have to check the value being passed to txtDepartment.Text and vice -versa.
I think the above answer is correct and he find the issues as well(Congrats). But the actual problem here is the Parameters.AddWithValue. It will not allows you to specify the type and will cause this kind of datatype conversion errors. So What i suggest you is, use Parameters.Add() instead for Parameters.AddWithValue() So that you can specify the type of expecting data and there by able to validate the input. you can see the below example(which help you to solve the issue as well):
cmd.Parameters.Add("#d28", SqlDbType.Int).Value = int.Parse(txtID.Text.Trim());
Where SqlDbType is an Enumeration which Specifies SQL Server-specific data type of a field, property, for use in a SqlParameter. int.TryParse() will be another best suggestion for you to perform error free conversion from string to integer.
Update : It seems The SP accepts values of different types, but you are giving all as string(.Text). This will create the same issue, So changing only "#d28" will not solve the issue, Try to read the attached link and make necessary changes in the code.

How can retrieve both a result set and a PRINT message from a SQL stored procedure in C#?

I have a stored procedure that can return both a PRINT message and regular query results from a SELECT statement. Using the elegant solution provided in this thread, I can easily capture my PRINT message when invoking SqlCommand.ExecuteNonQuery() in my C# code. The problem is, I also want to return my result set.
When I use a SqlDataReader to get back the query results from my stored proc using SqlCommand.ExecuteReader, the event handler that captures my PRINT message never fires like it does when I use SqlCommand.ExecuteNonquery.
It's beginning to seem like I can only have one or the other. Is there a way for me to capture both my PRINT message and my query results?
Here's a snippet of my SQL stored procedure:
IF EXISTS
(
SELECT MFG_PART_NUMBER, COUNT(*) AS RecordCount
FROM [PartsManagement].[ManufacturerCatalogPart]
WHERE CatalogID = #CatalogID
GROUP BY MFG_PART_NUMBER
HAVING COUNT(*) > 1
)
BEGIN
SELECT MFG_PART_NUMBER, COUNT(*) AS RecordCount
FROM [PartsManagement].[ManufacturerCatalogPart]
WHERE CatalogID = #CatalogID
GROUP BY MFG_PART_NUMBER
HAVING COUNT(*) > 1;
PRINT 'The update was not executed because duplicate MFG_PART_NUMBERs were found in the catalog. Delete the duplicates and try again.';
END;
And here's a snippet from my code:
//field
private string sqlPrintMessage = "";
//event handler for sql PRINT message
void myConnection_InfoMessage(object sender, SqlInfoMessageEventArgs e)
{
sqlPrintMessage = e.Message;
}
public void SomeMethod()
{
using (SqlConnection sqlcon = new SqlConnection(ConnectionManager.GetConnectionString()))
{
sqlcon.InfoMessage += new SqlInfoMessageEventHandler(myConnection_InfoMessage);
SqlCommand sqlcmd = new SqlCommand("[ManufacturerCatalogUpdate].[CheckCatalogForDuplicates]", sqlcon);
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("#CatalogID", catalogID);
sqlcon.Open();
//SqlDataReader reader = sqlcmd.ExecuteReader();
sqlcmd.ExecuteNonQuery();
if (sqlPrintMessage == "") //then proceed with update
{
//do some logic
}
else
{
//System.Diagnostics.Debug.WriteLine(sqlPrintMessage);
//List<DuplicatePartCount> duplicateParts = new List<DuplicatePartCount>();
//while (reader.Read())
//{
// DuplicatePartCount record = new DuplicatePartCount();
// record.MFG_PART_NUMBER = reader.GetString(0);
// record.count = reader.GetInt32(1);
// duplicateParts.Add(record);
//}
}
}
}
There are two way to do it based on selection of sql execution.
1) If you are using ExecuteNonQuery than use OUT param in sproc like below.
CREATE PROCEDURE GetEmployee
#employeeID INT,
#Message VarChar(100) OUTPUT
AS
BEGIN
-- Here is your result set from select statement
SELECT Emp_Name From Employee Where EmpId = #employeeID
-- Here is your message
SELECT #Message = 'Your Message!'
END
Now to get it in your code pass #Message parameter with OUTlike below.
//Add the output parameter to the command object
SqlParameter outPutParameter = new SqlParameter();
outPutParameter.ParameterName = “#Message”;
outPutParameter.SqlDbType = System.Data.SqlDbType.Varchar;
outPutParameter.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(outPutParameter);
cmd.ExecuteNonQuery();
//Retrieve the value of the output parameter
string Message = outPutParameter.Value.ToString();
// You can get remaining result set as always
2) If you are using Reader than....
Set the message and use Select statement instead of print.Like below'
SELECT Emp_Name From Employee Where EmpId = #employeeID
-- It should be set previously
SELECT #Message
To get in your code just Use
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
//Your result set or message
}
if(reader.NextResult())
{
while (reader.Read())
{
//Your result set or message
}
}
}
So, I think we first need to rethink the operation here. You want to do a duplicate as a test to determine if the app code should proceed or not. The proc returns a result set and then prints a message if there are dupes, else returns neither. And you are inferring that there will be a result set based on the existence of a captured message. That type of indirect test is less than ideal and unnecessary.
A direct and simpler method is available to test for the existence of a result set. Forget the message (especially since you aren't even using it) and instead just check the data reader:
if (reader.HasRows())
{
//System.Diagnostics.Debug.WriteLine(sqlPrintMessage);
//List<DuplicatePartCount> duplicateParts = new List<DuplicatePartCount>();
//while (reader.Read())
//{
// DuplicatePartCount record = new DuplicatePartCount();
// record.MFG_PART_NUMBER = reader.GetString(0);
// record.count = reader.GetInt32(1);
// duplicateParts.Add(record);
//}
}
else
{
//do some logic
}
If you are still just curious about the PRINT message getting trapped, do these two tests:
First, add a second System.Diagnostics.Debug.WriteLine(sqlPrintMessage); AFTER the while loop, and re-run the test
Second, without removing the 2nd debug line from #1, add a second PRINT command between the BEGIN and SELECT, with different text so that you can distinguish between them if necessary, and re-run the test
Also, the following "Remarks" from the MSDN page for the SqlConnection.FireInfoMessageEventOnUserErrors property might shed some light on this behavior:
When you set FireInfoMessageEventOnUserErrors to true, errors that were previously treated as exceptions are now handled as InfoMessage events. All events fire immediately and are handled by the event handler. If is FireInfoMessageEventOnUserErrors is set to false, then InfoMessage events are handled at the end of the procedure.
So, if you wanted / needed the messages as they happen, then you can set FireInfoMessageEventOnUserErrors to true, but that might alter the behavior of catching exceptions that might be more undesirable than getting the messages immediately.

How to check if a row is present in SQL Server table or not?

I am trying to check if there is a row present in a SQL Server table or not.
If the row exists (on a particular TicketID), it should show a messagebox that you can't continue further as there is already an entry in database. But if there isn't, it should insert some records (on that particular TicketID).
I tried try and catch but wasn't able to do it :
Here is the code of query: (hardcoded ticketID for example)
bool no;
try
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ST"].ConnectionString.ToString());
con.Open();
cmd.CommandText = "SELECT EngineerVisited from tblTicketTechnical where TicketID=1";
cmd.Connection = con;
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
bool = rdr.GetBoolean(0);
}
con.Close();
}
catch
{
MessageBox.Show("Cannot continue");
}
I would really appreciate if someone could suggest a function that will return true if row is found and return false, if it isn't.
You should follow the same logic in code as the logic you state in English: if there's already a ticket show a message and if not, insert some data.
var checkQuery = "SELECT COUNT(*) FROM tblTicketTechnical where TicketID=1";
var command = new OleDbCommand(checkQuery, con);
con.Open();
int count = (int)command.ExecuteScalar();
if(count > 0)
{
//Already exists, show message
}
else
{
var insertQuery = "INSERT INTO tblTicketTechnical(col1, col2) VALUES('val1', val2')";
con = new OleDbCommand(insertQuery, con);
con.ExecuteNonQuery();
}
Please mind that this is written out of my head and not tested. Nor have I implemented exception handling. This is just to show the logic how you can perform what you want to achieve.
You can use HasRows property of SQLDataReader.
A catch block will only be executed if your code throws an exception. Here it is simply not happening.
Instead of Try/Catch use if statements and checks on your query results.
Create procedure and code like this
IF NOT EXISTS (SELECT 1 FROM youtable WHERE id= #id)
BEGIN
RAISERROR ('Record Exists', 16, 2)
END
ELSE
Begin
INSERT INTO YOURTABEL(COLUM1,COLUM2) VALUES(VALUE1, VALUE2)
END
and then by try catch you can show message to user
You can use DataTableReader.HasRows Property
The HasRows property returns information about the current result set

bool doesExist = command.ExecuteScalar() != null for some reason evaluates to true constantly [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
ExecuteScalar returns null or DBNull (development or production server)
I have a stored procedure that checks to see if a pre-existing file id is associated to an item. If the select statement returns values, it should be true and assign "true" to the bool. however when the select statement returns a null because it doesn't exist, my code behind still makes the .Execute return "true"
This is my stored proc:
ALTER PROCEDURE [dbo].[Events_TaskIDExists]
#EventID int
AS
BEGIN
select TaskID from Events where EventID = #EventID
END
and here is my code behind:
public void hasTaskAssociatedToNote()
{
String[] Notes = hidSelectedEventIDs.Value.Split(',');
bool exists = false;
foreach (var note in Notes)
{
var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["OSCIDConnectionString"].ToString());
var command = new SqlCommand("Events_TaskIDExists", connection);
command.Parameters.Add(new SqlParameter("#EventID", SqlDbType.Int));
command.Parameters["#EventID"].Value = Convert.ToInt32(note.Trim());
command.CommandType = CommandType.StoredProcedure;
try
{
connection.Open();
exists = command.ExecuteScalar() != null;//causes true when it returns null......
var temp = command.ExecuteScalar();//this was just to check something else
if (exists)
{
exhibitWarning.Visible = true;
Warning1.Text = "There is an existing Task associated 0.";
}
}
catch (SqlException sql)
{
lblStatus.Text = "Couldn't connect to the Database - Error";
lblStatus.ForeColor = System.Drawing.Color.Red;
}
catch (Exception ex)
{
lblStatus.Text = "An error occured";
lblStatus.ForeColor = System.Drawing.Color.Red;
}
finally
{
if (connection.State == ConnectionState.Open)
connection.Close();
}
}
}
Your exists variable should be set as:
object result = command.ExecuteScalar();
exists = result != DBNull.Value && result != null;
A null result from SqlCommand.ExecuteScalar() returns a DBNull.Value, not null. Only an empty result set will return a null.
Since you're selecting TaskID based on EventID, my guess is that you don't have your database constrained to require a TaskID for every Event, and thus you have null TaskID fields. In other words, you have the Event record containing #EventID, but not an associated Task record (based on TaskID). This condition will return a DBNull.Value rather than a null.
"Return Value Type: System.Object The first column of the first
row in the result set, or a null reference (Nothing in Visual Basic)
if the result set is empty. Returns a maximum of 2033 characters." -
MSDN -
SqlCommand.ExecuteScalar()
I'd probably shotgun this and just
exists = (command.ExecuteScalar() ?? DBNull.Value) != DBNull.Value;
this assumes that for some reason your stored procedure is actually returning a row that has it's first column equal to DBNull, and that in that case you want exists == false. A short debug should prove or disprove that.

SQL Server and how to handle the type of error without conflict

I use SQL Server 2008 and ASP.NET C# and I have a stored procedure that returns some calculated rows.
I want to check the parameters values before doing the process and I want to return a custom error message if the parameters values are wrong.
In the UI side, I must return a different text and use a different window according to the error type. Example:
Errors when the parameters values are wrong.
Non handled errors.
I currently use this kind of SP in the database, but I tried to use the state argument and even the severity argument to identify the type of error. But I have some conflicts with non handled error returning the same state number than my parameter error, and so the wrong window comes up. If I use the severity level, I guess the SP could return an error with the same severity number as well in some cases.
I give you a quick example to have a better view:
CREATE PROCEDURE dbo.GetData
#Date1 date,
#Date2 date
AS
BEGIN
-- check the parameters
IF #Date2 < #Date1
BEGIN
RAISERROR(N'Date 2 cannot be less than Date 1', 16, 2); -- <= Here State 2
return
END
-- process here...
DECLARE #Table1 TABLE ( name nvarchar(50) NOT NULL)
-- Supposing you have to insert a row with a NULL value
INSERT INTO #Table1 VALUES (NULL);
-- Thus, this query returns this error with the state 2 as well!
--Msg 515, Level 16, State 2, Procedure GetData, Line 21
--Cannot insert the value NULL into column 'name', table '#Table1'; column does not allow nulls. INSERT fails.
SELECT 'Record 1';
SELECT 'Record 2';
END
From c#:
List<string> data = new List<string>();
protected void Button1_Click(object sender, EventArgs e)
{
string errorMessage = string.Empty;
bool isErrorFromChecking = false;
if (GetValues(ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString,
new DateTime(2011, 01, 01), new DateTime(2011, 02, 01),
ref isErrorFromChecking, ref errorMessage))
{
Label1.Text = data[0].ToString();
return;
}
if (isErrorFromChecking)
{
Label1.Text = errorMessage;
return;
}
Label1.Text = string.Format("Internal Error: {0}.", errorMessage);
}
private bool GetValues(string connectionString, DateTime date1, DateTime date2,
ref bool isErrorFromChecking, ref string errorMessage)
{
data = new List<string>();
try
{
using (SqlConnection sqlCon = new SqlConnection(connectionString))
{
sqlCon.Open();
SqlCommand sqlCmd = new SqlCommand();
sqlCmd.Connection = sqlCon;
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.CommandText = "dbo.GetData";
sqlCmd.Parameters.AddWithValue("Date1", date1);
sqlCmd.Parameters.AddWithValue("Date2", date2);
SqlDataReader reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
data.Add(reader[0].ToString());
}
reader.Close();
sqlCon.Close();
}
}
catch (SqlException ex)
{
if (ex.State == 2)
{
isErrorFromChecking = true;
errorMessage = ex.Message;
return false;
}
isErrorFromChecking = false;
errorMessage = ex.Message;
return false;
}
catch (Exception ex)
{
isErrorFromChecking = false;
errorMessage = ex.Message;
return false;
}
return true;
}
In the code above, the dates are correct but the program does not return the message “Internal Error: …” although the SP had an error.
I have some ideas, but I just want to know your point of view and the best way to do it.
Thanks.
According to this http://msdn.microsoft.com/en-us/library/ms178592.aspx you will get a message id of 50000 when you provides the message string yourself. I guess you could test for that in your C# code.
Or you could specify a MsgID (Value > 50000) in the SP instead and provide the error message based on the MsgID in the client code.
Simply split the logic in to two. By this I mean have the 'parameter check' logic in one Stored Procedure and the rest in another SP.
In the 'check' SP use output parameters to get any codes or error text you want returned.
The second SP can also call SP first to ensure it's not getting sent bad data.
The C# should then call the 'check' SP first and see what is returned.
Alternative is to use an output parameter for the error condition and return an empty dataset.
CREATE PROCEDURE spTest (#param1 int, #ErrorText varchar(50) OUTPUT )
AS
BEGIN
SET #ErrorText = NULL
IF #Param1 = 1
BEGIN
SET #ErrorText = 'I really cant except 1 as a parameter'
SELECT NULL as QueryPlaceholderCol
END
ELSE
BEGIN
SELECT 3.141 AS QueryPlaceholderCol
END
END
To test in T-SQL:
DECLARE #ReturnedError VARCHAR(50)
EXEC spTest 1,#ReturnedError OUTPUT
SELECT CASE WHEN #ReturnedError IS NULL THEN 'Worked Fine' ELSE #ReturnedError END AS Outputs
EXEC spTest 1423,#ReturnedError OUTPUT
SELECT CASE WHEN #ReturnedError IS NULL THEN 'Worked Fine' ELSE #ReturnedError END AS Outputs

Categories